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
.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
30ce93c56557cea2f384a47b549fb893700523a5 assets/create/lang/unfinished/de_de.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
b1935e7f8d79d1112e1685adb42daedb976ac6d7 assets/create/lang/unfinished/ja_jp.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
13b55d6e905a02403d2e95e9ba2357f99c5f2241 data/create/tags/blocks/fan_heaters.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
6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.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.at_current_speed": "at current speed",
"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.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress",

View file

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

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 730",
"_": "Missing Localizations: 666",
"_": "->------------------------] Game Elements [------------------------<-",
@ -10,83 +10,83 @@
"block.create.adjustable_pulse_repeater": "Répéteur d'impulsions réglable",
"block.create.adjustable_repeater": "Répéteur réglable",
"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_slab": "Dalle 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_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_slab": "Dalles 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_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_pillar": "Pilier en andésite",
"block.create.andesite_tunnel": "Tunnel en andésite",
"block.create.basin": "Bassin",
"block.create.belt": "Tapis roulant",
"block.create.birch_window": "Fenêtre en bouleau",
"block.create.birch_window_pane": "UNLOCALIZED: Birch Window Pane",
"block.create.black_sail": "UNLOCALIZED: Black Sail",
"block.create.black_seat": "UNLOCALIZED: Black Seat",
"block.create.black_valve_handle": "UNLOCALIZED: Black Valve Handle",
"block.create.blaze_burner": "UNLOCALIZED: Blaze Burner",
"block.create.blue_sail": "UNLOCALIZED: Blue Sail",
"block.create.blue_seat": "UNLOCALIZED: Blue Seat",
"block.create.blue_valve_handle": "UNLOCALIZED: Blue Valve Handle",
"block.create.brass_belt_funnel": "UNLOCALIZED: Brass Belt Funnel",
"block.create.brass_block": "UNLOCALIZED: Brass Block",
"block.create.brass_casing": "Boîtier en laiton",
"block.create.brass_encased_shaft": "UNLOCALIZED: Brass Encased Shaft",
"block.create.brass_funnel": "UNLOCALIZED: Brass Funnel",
"block.create.brass_tunnel": "UNLOCALIZED: Brass Tunnel",
"block.create.brown_sail": "UNLOCALIZED: Brown Sail",
"block.create.brown_seat": "UNLOCALIZED: Brown Seat",
"block.create.brown_valve_handle": "UNLOCALIZED: Brown Valve Handle",
"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.chiseled_dark_scoria": "UNLOCALIZED: Chiseled Dark Scoria",
"block.create.chiseled_dolomite": "UNLOCALIZED: Chiseled Dolomite",
"block.create.chiseled_gabbro": "UNLOCALIZED: Chiseled Gabbro",
"block.create.chiseled_limestone": "UNLOCALIZED: Chiseled Limestone",
"block.create.chiseled_scoria": "UNLOCALIZED: Chiseled Scoria",
"block.create.chiseled_weathered_limestone": "UNLOCALIZED: Chiseled Weathered Limestone",
"block.create.chocolate": "UNLOCALIZED: Chocolate",
"block.create.chute": "UNLOCALIZED: Chute",
"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.clutch": "Embrayage",
"block.create.cogwheel": "Roue dentée",
"block.create.content_observer": "UNLOCALIZED: Content Observer",
"block.create.controller_rail": "UNLOCALIZED: Controller Rail",
"block.create.content_observer": "Observateur de contenu",
"block.create.controller_rail": "Rails controlleurs",
"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_shingles": "Bardeaux de cuivre",
"block.create.copper_tiles": "UNLOCALIZED: Copper Tiles",
"block.create.copper_valve_handle": "UNLOCALIZED: Copper Valve Handle",
"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_fluid_tank": "UNLOCALIZED: Creative Fluid Tank",
"block.create.creative_fluid_tank": "Réservoir créatif",
"block.create.creative_motor": "Moteur",
"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.cyan_sail": "UNLOCALIZED: Cyan Sail",
"block.create.cyan_seat": "UNLOCALIZED: Cyan Seat",
"block.create.cyan_valve_handle": "UNLOCALIZED: Cyan Valve Handle",
"block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window",
"block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane",
"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_bricks": "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_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_stairs": "UNLOCALIZED: Dark Scoria Cobblestone Stairs",
"block.create.dark_scoria_cobblestone_wall": "UNLOCALIZED: Dark Scoria Cobblestone Wall",
"block.create.dark_scoria_pillar": "UNLOCALIZED: Dark Scoria Pillar",
"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_slab": "UNLOCALIZED: Diorite Bricks Slab",
"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_wall": "UNLOCALIZED: Diorite Cobblestone Wall",
"block.create.diorite_pillar": "UNLOCALIZED: Diorite Pillar",
"block.create.dolomite": "Dolomie",
"block.create.dolomite_bricks": "Briques de dolomie",
"block.create.dolomite_bricks_slab": "Dalle de briques de dolomie",
"block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomie",
"block.create.dolomite_bricks_wall": "Muret de briques de dolomie",
"block.create.dolomite": "Dolomite",
"block.create.dolomite_bricks": "Briques de dolomite",
"block.create.dolomite_bricks_slab": "Dalle de briques de dolomite",
"block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomite",
"block.create.dolomite_bricks_wall": "Muret de briques de dolomite",
"block.create.dolomite_cobblestone": "UNLOCALIZED: Dolomite Cobblestone",
"block.create.dolomite_cobblestone_slab": "UNLOCALIZED: Dolomite Cobblestone Slab",
"block.create.dolomite_cobblestone_stairs": "UNLOCALIZED: Dolomite Cobblestone Stairs",
"block.create.dolomite_cobblestone_wall": "UNLOCALIZED: Dolomite Cobblestone Wall",
"block.create.dolomite_pillar": "Pillier de dolomie",
"block.create.encased_chain_drive": "UNLOCALIZED: Encased Chain Drive",
"block.create.encased_fan": "Ventilateur enfermé",
"block.create.dolomite_pillar": "Pillier de dolomite",
"block.create.encased_chain_drive": "Chaine de transmission",
"block.create.encased_fan": "Ventilateur enchâssé",
"block.create.encased_fluid_pipe": "UNLOCALIZED: Encased Fluid Pipe",
"block.create.fancy_andesite_bricks": "UNLOCALIZED: Fancy Andesite Bricks",
"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_seat": "UNLOCALIZED: Pink Seat",
"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_slab": "UNLOCALIZED: Polished Dark Scoria Slab",
"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_dolomite": "Dolomie polie",
"block.create.polished_dolomite": "Dolomite polie",
"block.create.polished_dolomite_slab": "UNLOCALIZED: Polished Dolomite Slab",
"block.create.polished_dolomite_stairs": "UNLOCALIZED: Polished Dolomite Stairs",
"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_stairs": "UNLOCALIZED: Polished Scoria Stairs",
"block.create.polished_scoria_wall": "UNLOCALIZED: Polished Scoria Wall",
"block.create.polished_weathered_limestone": "Calcaire patinées polies",
"block.create.polished_weathered_limestone_slab": "Dalle de calcaire patinées",
"block.create.polished_weathered_limestone": "Calcaire altéré polies",
"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_wall": "UNLOCALIZED: Polished Weathered Limestone Wall",
"block.create.portable_fluid_interface": "UNLOCALIZED: Portable Fluid Interface",
@ -346,7 +346,7 @@
"block.create.red_sail": "UNLOCALIZED: Red Sail",
"block.create.red_seat": "UNLOCALIZED: Red Seat",
"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.refined_radiance_casing": "UNLOCALIZED: Radiant Casing",
"block.create.reinforced_rail": "UNLOCALIZED: Reinforced Rail",
@ -369,7 +369,7 @@
"block.create.secondary_linear_chassis": "UNLOCALIZED: Secondary Linear Chassis",
"block.create.sequenced_gearshift": "Décaleur de rotation séquencé",
"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_fluid_pipe": "UNLOCALIZED: Smart Fluid Pipe",
"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_pane": "Vitre encadrée verticale",
"block.create.water_wheel": "Roue à eau",
"block.create.weathered_limestone": "Calcaire patinées",
"block.create.weathered_limestone_bricks": "Briques de calcaire patinées",
"block.create.weathered_limestone_bricks_slab": "Dalle de briques de calcaire patinées",
"block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de calcaire patinées",
"block.create.weathered_limestone_bricks_wall": "Muret de briques de calcaire patinées",
"block.create.weathered_limestone": "Calcaire altéré",
"block.create.weathered_limestone_bricks": "Briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_slab": "Dalle de briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de Calcaire altéré",
"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_slab": "UNLOCALIZED: Weathered Limestone Cobblestone Slab",
"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_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_seat": "UNLOCALIZED: White Seat",
"block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle",
@ -478,7 +478,7 @@
"item.create.schematic_and_quill": "Schéma et plume",
"item.create.shadow_steel": "Acier sombre",
"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.wand_of_symmetry": "Bâton de symétrie",
"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.its_alive": "Ça bouge!",
"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.overstressed": "Surtension",
"advancement.create.overstressed.desc": "Testez d'abord les limites de la force mécanique",
@ -657,7 +657,7 @@
"itemGroup.create.base": "Create",
"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_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",
@ -796,10 +796,10 @@
"create.contraptions.movement_mode": "Mode de mouvement",
"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_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_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.rotate": "UNLOCALIZED: Always face toward motion",
"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.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.slime_added": "Bruit de slime",
"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.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.control1": "Lorsque Ctrl enfoncé",
"item.create.example_item.tooltip.control1": "Quand Ctrl enfoncé",
"item.create.example_item.tooltip.action1": "Ces commandes sont affichées.",
"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.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.control1": "Clic droit au sol",
"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.action3": "Ouvre l'_interface_ _de_ _configuration_",
"item.create.tree_fertilizer.tooltip": "ENGRAIS POUR ARBRE",
"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.condition1": "Lorsqu'utilisé sur une pousse d'arbre",
"item.create.tree_fertilizer.tooltip.behaviour1": "Fait pousser des arbres _indépendamment_ de leurs _conditions_ _d'emplacement_",
"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'rotors communs.",
"item.create.tree_fertilizer.tooltip.condition1": "Lorsqu'utilisé sur une pousse d'rotor",
"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.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.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder.",
@ -1340,14 +1340,14 @@
"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.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.condition2": "Clic droit",
"item.create.filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.",
"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.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.condition2": "Clic droit",
"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.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.control1": "Clic droit en étant accroupi",
"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.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.shaft.tooltip": "ARBRE MÉCANIQUE",
"block.create.shaft.tooltip.summary": "_Relais_ la _rotation_ en ligne droite.",
"block.create.shaft.tooltip": "ROTOR",
"block.create.shaft.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite.",
"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.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.summary": "_Relais_ la _rotation_ en ligne droite. Convient pour propager la rotation à travers les murs.",
"block.create.encased_shaft.tooltip": "ROTOR ENCASTRÉ",
"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.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.summary": "Une commande pour basculer le sens de rotation des arbres connectés.",
"block.create.gearshift.tooltip": "BOÎTE DE VITESSES",
"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.behaviour1": "_Inverse_ la rotation sortante.",
"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.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.",
"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.control1": "Clic droit sur arbre",
"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.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 rotor",
"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.action2": "_Réinitialise_ la première position sélectionnée pour le tapis roulant.",
"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.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.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.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.control1": "Clic droit a kinetic block",
"item.create.wrench.tooltip.action1": "_Tourne_ les _composents_ proche ou loin de la face avec lequel vous avez interagi.",
"item.create.wrench.tooltip.control1": "Clic droit sur un bloc de Create",
"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.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.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.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.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.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.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.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.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.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.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.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.mechanical_press.tooltip": "PRESSE MÉCANIQUE",
@ -1511,11 +1511,11 @@
"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.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.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.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.",
@ -1537,7 +1537,7 @@
"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.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.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.",
@ -1555,17 +1555,17 @@
"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.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.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.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.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.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.windmill_bearing.tooltip": "UNLOCALIZED: WINDMILL BEARING",
@ -1583,20 +1583,20 @@
"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.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.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.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.condition2": "Clic droit",
"block.create.sequenced_gearshift.tooltip.behaviour2": "Ouvre _l'interface_ _de_ _configuration_",
"block.create.cart_assembler.tooltip": "ASSEMBLEUR DE CHARIOT",
"block.create.cart_assembler.tooltip.summary": "Monte une structure connectée sur un _chariot_ _passant_.",
"block.create.cart_assembler.tooltip": "ASSEMBLEUR DE WAGON",
"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.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.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",
@ -1608,35 +1608,35 @@
"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.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.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.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.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.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.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.summary": "UNLOCALIZED: A second type of _Linear Chassis_ that does not connect to the other.",
"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.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.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.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.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.condition2": "Lorsqu'en mouvement",
"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.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.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.condition1": "UNLOCALIZED: While Moving",
"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": "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.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.condition1": "Lorsque 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.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": "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. 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.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.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.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.behaviour1": "Arrête de fournir de _l'énergie_",
"block.create.content_observer.tooltip": "UNLOCALIZED: CONTENT OBSERVER",
"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": "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.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.condition1": "Lorsqu'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": "LIEN DE REDSTONE",
"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": "Quand alimenté",
"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.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.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.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.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.summary": "N'émet de l'énergie que par paires. Il est mobile avec _pistons_ _mécaniques_ ou _roulements_.",
"block.create.redstone_contact.tooltip.condition1": "Lorsque tourné vers un autre redstone_contact",
"block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ _redstone_.",
"block.create.redstone_contact.tooltip.condition2": "Lorsqu'en mouvement",
"block.create.redstone_contact.tooltip.behaviour2": "Déclenche tous les redstone_contacts fixes qu'il passe.",
"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 des _pistons_ _mécaniques_ ou _roulements_.",
"block.create.redstone_contact.tooltip.condition1": "Quand tourné vers un autre contact de redstone",
"block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ de _redstone_.",
"block.create.redstone_contact.tooltip.condition2": "Quand en mouvement",
"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.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.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.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.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.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.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.condition3": "UNLOCALIZED: When Filter assigned",
"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.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.summary": "Boîtier de machine robuste avec une variété d'utilisations. Sans danger pour la décoration.",
"block.create.brass_casing.tooltip": "REVÊTEMENT EN LAITON",
"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.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.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.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.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.",
"item.create.sand_paper.tooltip": "UNLOCALIZED: SAND PAPER",
"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.condition1": "UNLOCALIZED: When Used",
"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": "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": "UNLOCALIZED: SUPER GLUE",
"item.create.super_glue.tooltip.summary": "UNLOCALIZED: Glue a block to another, and they will forever be inseparable.",
"item.create.super_glue.tooltip.condition1": "UNLOCALIZED: When Used",
"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.condition2": "UNLOCALIZED: When Held in Offhand",
"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": "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": "UNLOCALIZED: BUILDERS TEA",
"item.create.builders_tea.tooltip.summary": "UNLOCALIZED: The perfect drink to get the day started- _Motivating_ and _Saturating._",
"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.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.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.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.",
@ -1780,7 +1780,7 @@
"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.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.randomWipDescription5": "Croyez-moi, c'est inutile.",
"create.tooltip.randomWipDescription6": "En utilisant cet article, vous êtes responsables et acceptez ses conditions.",

View file

@ -23,6 +23,7 @@
"create:redstone_link",
"create:analog_lever",
"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_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.simibubi.create.AllBlocks;
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 mezz.jei.api.constants.VanillaTypes;

View file

@ -38,7 +38,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity {
if (!(tileEntity instanceof KineticTileEntity))
return;
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;
}

View file

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

View file

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

View file

@ -1,6 +1,5 @@
package com.simibubi.create.content.contraptions.components.fan;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
@ -33,9 +32,16 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
@Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onBlockAdded(state, worldIn, pos, oldState, isMoving);
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
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())) {
@ -70,13 +76,13 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
.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)
return;
notifyFanTile(worldIn, pos);
if (worldIn.isRemote)
if (worldIn.isRemote())
return;
withTileEntityDo(worldIn, pos, te -> te.updateGenerator(state.get(FACING)));
withTileEntityDo(worldIn, pos, te -> te.queueGeneratorUpdate());
}
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 com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
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.world.World;
@MethodsReturnNonnullByDefault
public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements IAirCurrentSource {
@ -27,17 +27,20 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
protected int entitySearchCooldown;
protected boolean isGenerator;
protected boolean updateAirFlow;
protected boolean updateGenerator;
public EncasedFanTileEntity(TileEntityType<? extends EncasedFanTileEntity> type) {
super(type);
isGenerator = false;
airCurrent = new AirCurrent(this);
updateAirFlow = true;
updateGenerator = false;
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
super.read(compound, clientPacket);
if (!wasMoved)
isGenerator = compound.getBoolean("Generating");
if (clientPacket)
airCurrent.rebuild();
@ -64,12 +67,20 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
return isGenerator ? AllConfigs.SERVER.kinetics.generatingFanSpeed.get() : 0;
}
public void updateGenerator(Direction facing) {
boolean shouldGenerate = world.isBlockPowered(pos) && facing == Direction.DOWN
&& world.isBlockPresent(pos.down()) && blockBelowIsHot();
if (shouldGenerate == isGenerator)
public void queueGeneratorUpdate() {
updateGenerator = true;
}
public void updateGenerator() {
BlockState blockState = getBlockState();
if (!AllBlocks.ENCASED_FAN.has(blockState))
return;
if (blockState.get(EncasedFanBlock.FACING) != Direction.DOWN)
return;
boolean shouldGenerate = world.isBlockPowered(pos) && world.isBlockPresent(pos.down()) && blockBelowIsHot();
if (shouldGenerate == isGenerator)
return;
isGenerator = shouldGenerate;
updateGeneratedRotation();
}
@ -171,6 +182,11 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
sendData();
}
if (updateGenerator) {
updateGenerator = false;
updateGenerator();
}
if (getSpeed() == 0 || isGenerator)
return;

View file

@ -153,6 +153,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class,
new AxisAlignedBB(pos.down()).shrink(.125f))) {
if (!itemEntity.isAlive() || !itemEntity.onGround)
continue;
ItemStack stack = itemEntity.getItem();
Optional<PressingRecipe> recipe = getRecipe(stack);
if (!recipe.isPresent())
@ -233,7 +235,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
if (!(entity instanceof ItemEntity))
continue;
if (!entity.isAlive())
if (!entity.isAlive() || !entity.onGround)
continue;
ItemEntity itemEntity = (ItemEntity) entity;
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 static boolean movementNecessary(World world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
public static boolean movementNecessary(BlockState state, World world, BlockPos pos) {
if (isBrittle(state))
return true;
if (state.getBlock() instanceof FenceGateBlock)
@ -68,18 +67,17 @@ public class BlockMovementTraits {
return true;
}
public static boolean movementAllowed(World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
public static boolean movementAllowed(BlockState state, World world, BlockPos pos) {
Block block = state.getBlock();
if (block instanceof AbstractChassisBlock)
return true;
if (blockState.getBlockHardness(world, pos) == -1)
if (state.getBlockHardness(world, pos) == -1)
return false;
if (AllBlockTags.NON_MOVABLE.matches(blockState))
if (AllBlockTags.NON_MOVABLE.matches(state))
return false;
// 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;
if (block instanceof MechanicalBearingBlock) {
TileEntity te = world.getTileEntity(pos);
@ -97,11 +95,11 @@ public class BlockMovementTraits {
return !((PulleyTileEntity) te).running;
}
if (AllBlocks.BELT.has(blockState))
if (AllBlocks.BELT.has(state))
return true;
if (blockState.getBlock() instanceof GrindstoneBlock)
if (state.getBlock() instanceof GrindstoneBlock)
return true;
return blockState.getPushReaction() != PushReaction.BLOCK;
return state.getPushReaction() != PushReaction.BLOCK;
}
/**
@ -227,6 +225,12 @@ public class BlockMovementTraits {
if (state.getBlock() instanceof SailBlock)
return facing.getAxis() == state.get(SailBlock.FACING)
.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);
}

View file

@ -1,28 +1,8 @@
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.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.base.IRotate;
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.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.piston.MechanicalPistonBlock;
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.pulley.PulleyBlock;
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.Iterate;
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.worldWrappers.WrappedWorld;
import net.minecraft.block.AbstractButtonBlock;
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.block.*;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity;
import net.minecraft.fluid.Fluids;
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.ChestType;
import net.minecraft.state.properties.DoubleBlockHalf;
import net.minecraft.state.properties.PistonType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
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.items.IItemHandlerModifiable;
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 {
@ -134,9 +120,9 @@ public abstract class Contraption {
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();
@ -149,7 +135,7 @@ public abstract class Contraption {
}
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
List<BlockPos> frontier) {
Queue<BlockPos> frontier) throws AssemblyException {
return true;
}
@ -160,9 +146,9 @@ public abstract class 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();
List<BlockPos> frontier = new ArrayList<>();
Queue<BlockPos> frontier = new LinkedList<>();
Set<BlockPos> visited = new HashSet<>();
anchor = pos;
@ -176,10 +162,10 @@ public abstract class Contraption {
for (int limit = 100000; limit > 0; limit--) {
if (frontier.isEmpty())
return true;
if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited))
if (!moveBlock(world, forcedDirection, frontier, visited))
return false;
}
return false;
throw AssemblyException.structureTooLarge();
}
public void onEntityCreated(AbstractContraptionEntity entity) {
@ -191,8 +177,12 @@ public abstract class Contraption {
StabilizedContraption subContraption = new StabilizedContraption(face);
World world = entity.world;
BlockPos pos = blockFace.getPos();
try {
if (!subContraption.assemble(world, pos))
continue;
} catch (AssemblyException e) {
continue;
}
subContraption.removeBlocksFromWorld(world, BlockPos.ZERO);
OrientedContraptionEntity movedContraption =
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));
}
protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier,
Set<BlockPos> visited) {
visited.add(pos);
frontier.remove(pos);
if (!world.isBlockPresent(pos))
/** move the first block in frontier queue */
protected boolean moveBlock(World world, @Nullable Direction forcedDirection, Queue<BlockPos> frontier,
Set<BlockPos> visited) throws AssemblyException {
BlockPos pos = frontier.poll();
if (pos == null)
return false;
visited.add(pos);
if (World.isOutsideBuildHeight(pos))
return true;
if (!world.isBlockPresent(pos))
throw AssemblyException.unloadedChunk(pos);
if (isAnchoringBlockAt(pos))
return true;
if (!BlockMovementTraits.movementNecessary(world, pos))
return true;
if (!movementAllowed(world, pos))
return false;
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
&& !moveChassis(world, pos, forcedDirection, frontier, visited))
return false;
@ -266,25 +261,11 @@ public abstract class Contraption {
if (AllBlocks.BELT.has(state))
moveBelt(pos, frontier, visited, state);
if (AllBlocks.GANTRY_PINION.has(state)) {
BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING));
if (!visited.contains(offset))
frontier.add(offset);
}
if (AllBlocks.GANTRY_PINION.has(state))
moveGantryPinion(world, pos, frontier, visited, state);
if (AllBlocks.GANTRY_SHAFT.has(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);
}
}
moveGantryShaft(world, pos, frontier, visited, state);
// Bearings potentially create stabilized sub-contraptions
if (AllBlocks.MECHANICAL_BEARING.has(state))
@ -302,6 +283,10 @@ public abstract class Contraption {
if (state.getBlock() instanceof MechanicalPistonBlock)
if (!moveMechanicalPiston(world, pos, frontier, visited, state))
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
if (state.getBlock() instanceof DoorBlock) {
@ -311,22 +296,22 @@ public abstract class Contraption {
}
// Cart assemblers attach themselves
BlockState stateBelow = world.getBlockState(pos.down());
if (!visited.contains(pos.down()) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
frontier.add(pos.down());
BlockPos posDown = pos.down();
BlockState stateBelow = world.getBlockState(posDown);
if (!visited.contains(posDown) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
frontier.add(posDown);
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
// Slime blocks and super glue drag adjacent blocks if possible
boolean isStickyBlock = state.isStickyBlock();
for (Direction offset : Iterate.directions) {
BlockPos offsetPos = pos.offset(offset);
BlockState blockState = world.getBlockState(offsetPos);
if (isAnchoringBlockAt(offsetPos))
continue;
if (!movementAllowed(world, offsetPos)) {
if (offset == forcedDirection && isStickyBlock)
return false;
if (!movementAllowed(blockState, world, offsetPos)) {
if (offset == forcedDirection)
throw AssemblyException.unmovableBlock(pos, state);
continue;
}
@ -335,20 +320,112 @@ public abstract class Contraption {
boolean blockAttachedTowardsFace =
BlockMovementTraits.isBlockAttachedTowards(world, offsetPos, blockState, offset.getOpposite());
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);
if (faceHasGlue)
addGlue(superglue.get(offset));
}
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);
if (!canAxisBeStabilized(facing.getAxis())) {
if (!canBeStabilized(facing, pos.subtract(anchor))) {
BlockPos offset = pos.offset(facing);
if (!visited.contains(offset))
frontier.add(offset);
@ -357,7 +434,7 @@ public abstract class Contraption {
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 prevPos = BeltBlock.nextSegmentPosition(state, pos, false);
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();
BlockPos ropePos = pos;
while (limit-- >= 0) {
@ -396,53 +473,31 @@ public abstract class Contraption {
}
}
private boolean moveMechanicalPiston(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
private boolean moveMechanicalPiston(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) throws AssemblyException {
int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
Direction direction = state.get(MechanicalPistonBlock.FACING);
if (state.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
BlockPos searchPos = pos;
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)
PistonState pistonState = state.get(MechanicalPistonBlock.STATE);
if (pistonState == PistonState.MOVING)
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;
while (limit-- >= 0) {
searchPos = searchPos.offset(direction.getOpposite());
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;
}
break;
if (pistonState == PistonState.EXTENDED || MechanicalPistonBlock.isStickyPiston(state)) {
offset = pos.offset(direction);
if (!visited.contains(offset))
frontier.add(offset);
}
if (limit <= -1)
return false;
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) {
TileEntity te = world.getTileEntity(pos);
if (!(te instanceof ChassisTileEntity))
@ -527,8 +582,8 @@ public abstract class Contraption {
return globalPos.subtract(anchor);
}
protected boolean movementAllowed(World world, BlockPos pos) {
return BlockMovementTraits.movementAllowed(world, pos);
protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
return BlockMovementTraits.movementAllowed(state, world, pos);
}
protected boolean isAnchoringBlockAt(BlockPos pos) {
@ -825,6 +880,8 @@ public abstract class Contraption {
TileEntity tileEntity = world.getTileEntity(targetPos);
CompoundNBT tag = block.nbt;
if (tileEntity != null)
tag = NBTProcessors.process(tileEntity, tag, false);
if (tileEntity != null && tag != null) {
tag.putInt("x", targetPos.getX());
tag.putInt("y", targetPos.getY());
@ -855,9 +912,10 @@ public abstract class Contraption {
}
}
for (BlockInfo block : blocks.values()) {
BlockPos targetPos = transform.apply(block.pos);
if (!shouldUpdateAfterMovement(block))
continue;
BlockPos targetPos = transform.apply(block.pos);
BlockState state = world.getBlockState(targetPos);
world.markAndNotifyBlock(targetPos, null, block.state, block.state,
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 net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -48,7 +47,7 @@ public abstract class TranslatingContraption extends Contraption {
}
@Override
protected boolean canAxisBeStabilized(Axis axis) {
public boolean canBeStabilized(Direction facing, BlockPos localPos) {
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.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -29,7 +29,7 @@ public class BearingContraption extends Contraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockPos offset = pos.offset(facing);
if (!searchMovedStructure(world, offset, null))
return false;
@ -84,8 +84,10 @@ public class BearingContraption extends Contraption {
}
@Override
protected boolean canAxisBeStabilized(Axis axis) {
return axis == facing.getAxis();
public boolean canBeStabilized(Direction facing, BlockPos localPos) {
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;
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.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.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType;
import com.simibubi.create.foundation.advancement.AllTriggers;
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.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
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.math.BlockPos;
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 minuteHand;
@ -37,6 +37,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
protected boolean running;
protected boolean assembleNextTick;
protected AssemblyException lastException;
protected ScrollOptionBehaviour<ClockHands> operationMode;
@ -105,6 +106,11 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
applyRotations();
}
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected void applyRotations() {
BlockState blockState = getBlockState();
Axis axis = Axis.X;
@ -199,8 +205,15 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
Pair<ClockworkContraption, ClockworkContraption> contraption =
ClockworkContraption.assembleClockworkAt(world, pos, direction);
Pair<ClockworkContraption, ClockworkContraption> contraption;
try {
contraption = ClockworkContraption.assembleClockworkAt(world, pos, direction);
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (contraption == null)
return;
if (contraption.getLeft() == null)
@ -284,6 +297,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
compound.putBoolean("Running", running);
compound.putFloat("HourAngle", hourAngle);
compound.putFloat("MinuteAngle", minuteAngle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@ -295,6 +309,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
running = compound.getBoolean("Running");
hourAngle = compound.getFloat("HourAngle");
minuteAngle = compound.getFloat("MinuteAngle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
if (!clientPacket)

View file

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

View file

@ -1,12 +1,10 @@
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.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.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.TooltipHelper;
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.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
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.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 ControlledContraptionEntity movedContraption;
@ -31,6 +32,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
protected boolean running;
protected boolean assembleNextTick;
protected float clientAngleDiff;
protected AssemblyException lastException;
public MechanicalBearingTileEntity(TileEntityType<? extends MechanicalBearingTileEntity> type) {
super(type);
@ -62,6 +64,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
public void write(CompoundNBT compound, boolean clientPacket) {
compound.putBoolean("Running", running);
compound.putFloat("Angle", angle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@ -70,6 +73,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
float angleBefore = angle;
running = compound.getBoolean("Running");
angle = compound.getFloat("Angle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
if (!clientPacket)
return;
@ -104,6 +108,11 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
return speed;
}
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected boolean isWindmill() {
return false;
}
@ -120,9 +129,17 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
Direction direction = getBlockState().get(FACING);
BearingContraption contraption = new BearingContraption(isWindmill(), direction);
try {
if (!contraption.assemble(world, pos))
return;
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (isWindmill())
AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, world, pos, 5);
if (contraption.getSailBlocks() >= 16 * 8)
@ -281,5 +298,4 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
TooltipHelper.addHint(tooltip, "hint.empty_bearing");
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) {
ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.SAIL.isIn(heldItem) || AllBlocks.SAIL_FRAME.isIn(heldItem)) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, 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 (placementHelper.matchesItem(heldItem))
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (heldItem.getItem() instanceof ShearsItem) {
if (!world.isRemote)

View file

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

View file

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

View file

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

View file

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

View file

@ -10,11 +10,15 @@ import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
@ -34,10 +38,15 @@ public class GantryPinionBlock extends DirectionalAxisKineticBlock implements IT
.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
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onBlockAdded(state, worldIn, pos, oldState, isMoving);
withTileEntityDo(worldIn, pos, GantryPinionTileEntity::checkValidGantryShaft);
}
@Override
@ -50,6 +59,18 @@ public class GantryPinionBlock extends DirectionalAxisKineticBlock implements IT
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
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState stateForPlacement = super.getStateForPlacement(context);

View file

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

View file

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

View file

@ -1,13 +1,9 @@
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.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
@ -15,12 +11,8 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.*;
import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
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.network.PacketDistributor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@EventBusSubscriber
public class SuperGlueHandler {
@ -65,6 +61,8 @@ public class SuperGlueHandler {
return;
if (AllItems.WRENCH.isIn(placer.getHeldItemMainhand()))
return;
if (event.getPlacedAgainst() == IPlacementHelper.ID)
return;
double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE)
.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.AllShapes;
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.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
@ -229,14 +230,28 @@ public class CartAssemblerBlock extends AbstractRailBlock
.isCoupledThroughContraption())
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);
MountedContraption contraption = new MountedContraption(mode);
try {
if (!contraption.assemble(world, pos))
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;
Optional<Direction> initialOrientation = cart.getMotion()
.length() < 1 / 512f ? Optional.empty() : Optional.of(cart.getAdjustedHorizontalFacing());

View file

@ -1,7 +1,7 @@
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.tileEntity.SmartTileEntity;
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.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction.Axis;
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;
protected ScrollOptionBehaviour<CartMovementMode> movementMode;
private int ticksSinceMinecartUpdate;
protected AssemblyException lastException;
public CartAssemblerTileEntity(TileEntityType<? extends CartAssemblerTileEntity> type) {
super(type);
@ -44,6 +47,23 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
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() {
return new CartAssemblerValueBoxTransform();
}
@ -103,5 +123,4 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
public boolean isMinecartUpdateValid() {
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 java.util.List;
import java.util.Queue;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks;
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.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.foundation.utility.Iterate;
@ -52,7 +53,7 @@ public class MountedContraption extends Contraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockState state = world.getBlockState(pos);
if (!state.has(RAIL_SHAPE))
return false;
@ -70,7 +71,7 @@ public class MountedContraption extends Contraption {
}
@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.add(pos.up());
return true;
@ -104,11 +105,10 @@ public class MountedContraption extends Contraption {
}
@Override
protected boolean movementAllowed(World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(blockState))
return testSecondaryCartAssembler(world, blockState, pos);
return super.movementAllowed(world, pos);
protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(state))
return testSecondaryCartAssembler(world, state, pos);
return super.movementAllowed(state, world, pos);
}
protected boolean testSecondaryCartAssembler(World world, BlockState state, BlockPos pos) {
@ -149,7 +149,7 @@ public class MountedContraption extends Contraption {
}
@Override
protected boolean canAxisBeStabilized(Axis axis) {
public boolean canBeStabilized(Direction facing, BlockPos localPos) {
return true;
}

View file

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

View file

@ -1,13 +1,15 @@
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.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.CarpetBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.PistonType;
@ -22,6 +24,7 @@ import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE;
@ -50,7 +53,7 @@ public class PistonContraption extends TranslatingContraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!collectExtensions(world, pos, orientation))
return false;
int count = blocks.size();
@ -65,7 +68,7 @@ public class PistonContraption extends TranslatingContraption {
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<>();
BlockPos actualStart = pos;
BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
@ -88,7 +91,7 @@ public class PistonContraption extends TranslatingContraption {
nextBlock = world.getBlockState(actualStart.offset(direction));
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()));
if (extensionsInFront + extensionsInBack > MechanicalPistonBlock.maxAllowedPistonPoles())
return false;
throw AssemblyException.tooManyPistonPoles();
}
anchor = pos.offset(direction, initialExtensionProgress + 1);
@ -123,7 +126,7 @@ public class PistonContraption extends TranslatingContraption {
1, 1);
if (extensionLength == 0)
return false;
throw AssemblyException.noPistonPoles();
bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
@ -143,7 +146,7 @@ public class PistonContraption extends TranslatingContraption {
}
@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();
boolean sticky = isStickyPiston(world.getBlockState(pos.offset(orientation, -1)));
boolean retracting = direction != orientation;
@ -153,17 +156,24 @@ public class PistonContraption extends TranslatingContraption {
if (offset == 1 && retracting)
return true;
BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress);
if (!world.isBlockPresent(currentPos))
return false;
if (!BlockMovementTraits.movementNecessary(world, currentPos))
if (retracting && World.isOutsideBuildHeight(currentPos))
return true;
if (!world.isBlockPresent(currentPos))
throw AssemblyException.unloadedChunk(currentPos);
BlockState state = world.getBlockState(currentPos);
if (!BlockMovementTraits.movementNecessary(state, world, currentPos))
return true;
if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock))
return true;
if (isPistonHead(state) && state.get(FACING) == direction.getOpposite())
return true;
if (!BlockMovementTraits.movementAllowed(world, currentPos))
return retracting;
if (!BlockMovementTraits.movementAllowed(state, world, currentPos))
if (retracting)
return true;
else
throw AssemblyException.unmovableBlock(currentPos, state);
if (retracting && state.getPushReaction() == PushReaction.PUSH_ONLY)
return true;
frontier.add(currentPos);
if (BlockMovementTraits.notSupportive(state, orientation))
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.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 mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
@ -17,6 +16,7 @@ import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
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) {
ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.PISTON_EXTENSION_POLE.isIn(heldItem) && !player.isSneaking()) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, 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;
}
if (placementHelper.matchesItem(heldItem) && !player.isSneaking())
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
return ActionResultType.PASS;
}

View file

@ -1,5 +1,6 @@
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.TranslatingContraption;
@ -23,7 +24,7 @@ public class PulleyContraption extends TranslatingContraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!searchMovedStructure(world, pos, null))
return false;
startMoving(world);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
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.ContraptionCollider;
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.tileEntity.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.IWaterLoggable;
@ -42,12 +42,23 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
}
@Override
protected void assemble() {
protected void assemble() throws AssemblyException {
if (!(world.getBlockState(pos)
.getBlock() instanceof PulleyBlock))
return;
if (speed == 0)
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)
return;
if (offset <= 0 && getSpeed() < 0)
@ -70,7 +81,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
if (!canAssembleStructure && getSpeed() > 0)
return;
for (int i = ((int) offset); i > 0; i--) {
for (i = ((int) offset); i > 0; i--) {
BlockPos offset = pos.down(i);
BlockState oldState = world.getBlockState(offset);
if (oldState.getBlock() instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED)
@ -165,9 +176,10 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
return;
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;
if (BlockMovementTraits.isBrittle(world.getBlockState(posBelow)))
if (BlockMovementTraits.isBrittle(state))
return;
disassemble();

View file

@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Direction;
@ -45,22 +46,26 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayerEntity sender = context.get()
.getSender();
context.get().enqueueWork(() -> {
ServerPlayerEntity sender = context.get().getSender();
if (sender == null)
return;
Entity entityByID = sender.getServerWorld()
.getEntityByID(target);
Entity entityByID = sender.getServerWorld().getEntityByID(target);
if (!(entityByID instanceof AbstractContraptionEntity))
return;
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))
sender.swingHand(interactionHand, true);
});
context.get()
.setPacketHandled(true);
context.get().setPacketHandled(true);
}
}

View file

@ -21,9 +21,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.item.PotionItem;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.BlockParticleData;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.potion.PotionUtils;
import net.minecraft.tileentity.TileEntityType;
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.AllItems;
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.PistonExtensionPoleBlock;
import com.simibubi.create.foundation.config.AllConfigs;
@ -92,6 +93,14 @@ public class GoggleOverlayRenderer {
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
if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation))
return;

View file

@ -9,13 +9,13 @@ import java.util.List;
public interface IHaveGoggleInformation {
DecimalFormat decimalFormat = new DecimalFormat("#.##");
public static String spacing = " ";
String spacing = " ";
/**
* 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,
* or {{@code false}} if the overlay should not 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
* */
default boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking){
return false;

View file

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

View file

@ -1,10 +1,5 @@
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.AllShapes;
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.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault;
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.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
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.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 {
boolean large;
@ -47,49 +47,27 @@ public class CogwheelBlockItem extends BlockItem {
}
@Override
public ActionResultType tryPlace(BlockItemUseContext context) {
public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
World world = context.getWorld();
BlockPos pos = context.getPos()
.offset(context.getFace()
.getOpposite());
BlockPos pos = context.getPos();
BlockState state = world.getBlockState(pos);
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
PlayerEntity player = context.getPlayer();
if (helper.matchesState(state)) {
PlacementOffset offset = helper.getOffset(world, state, pos,
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;
BlockRayTraceResult ray = new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true);
if (helper.matchesState(state) && player != null && !player.isSneaking()) {
return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
}
if (integratedCogHelperId != -1) {
helper = PlacementHelpers.get(integratedCogHelperId);
if (helper.matchesState(state)) {
PlacementOffset offset = helper.getOffset(world, state, pos,
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 (helper.matchesState(state) && player != null && !player.isSneaking()) {
return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
}
}
return super.tryPlace(context);
return super.onItemUseFirst(stack, context);
}
@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.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 mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState;
@ -77,26 +76,8 @@ public class ShaftBlock extends AbstractShaftBlock {
}
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
if (helper.getItemPredicate().test(heldItem)) {
PlacementOffset offset = helper.getOffset(world, state, pos, 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;
}
if (helper.matchesItem(heldItem))
return helper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
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.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.material.Material;
import net.minecraft.block.material.MaterialColor;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.particles.RedstoneParticleData;
@ -114,6 +113,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
return context.getFace();
}
@Override
protected boolean getAxisAlignmentForPlacement(BlockItemUseContext context) {
return context.getPlacementHorizontalFacing().getAxis() != Axis.X;
}
@ -127,8 +127,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
return false;
if (getRotationAxis(state) == Axis.Y && face != state.get(FACING))
return false;
BlockState blockState = world.getBlockState(pos.offset(face));
if (Block.hasSolidSide(blockState, world, pos, face.getOpposite()) && blockState.getMaterial() != Material.GLASS
if (!Block.shouldSideBeRendered(state, world, pos, face)
&& !(world instanceof WrappedWorld))
return false;
return true;

View file

@ -5,6 +5,7 @@ import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Hand;
@ -53,15 +54,20 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase {
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayerEntity sender = context.get()
.getSender();
context.get().enqueueWork(() -> {
ServerPlayerEntity sender = context.get().getSender();
if (sender == null)
return;
Entity entityByID = sender.getServerWorld()
.getEntityByID(target);
Entity entityByID = sender.getServerWorld().getEntityByID(target);
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)
sender.attackTargetEntityWithCurrentItem(entityByID);
else if (specificPoint == null)
@ -70,8 +76,7 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase {
entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand);
}
});
context.get()
.setPacketHandled(true);
context.get().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.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -115,7 +116,7 @@ public abstract class ZapperItem extends Item {
});
applyCooldown(player, item, false);
}
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
return new ActionResult<>(ActionResultType.SUCCESS, item);
}
boolean mainHand = hand == Hand.MAIN_HAND;
@ -125,7 +126,7 @@ public abstract class ZapperItem extends Item {
// Pass To Offhand
if (mainHand && isSwap && gunInOtherHand)
return new ActionResult<ItemStack>(ActionResultType.FAIL, item);
return new ActionResult<>(ActionResultType.FAIL, item);
if (mainHand && !isSwap && gunInOtherHand)
item.getTag()
.putBoolean("_Swap", true);
@ -144,7 +145,7 @@ public abstract class ZapperItem extends Item {
world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS,
1f, 0.5f);
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();
@ -169,7 +170,7 @@ public abstract class ZapperItem extends Item {
// No target
if (pos == null || stateReplaced.getBlock() == Blocks.AIR) {
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
@ -183,7 +184,7 @@ public abstract class ZapperItem extends Item {
// Client side
if (world.isRemote) {
ZapperRenderHandler.dontAnimateItem(hand);
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item);
return new ActionResult<>(ActionResultType.SUCCESS, item);
}
// Server side
@ -195,7 +196,7 @@ public abstract class ZapperItem extends Item {
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) {
@ -240,10 +241,13 @@ public abstract class ZapperItem extends Item {
return UseAction.NONE;
}
public static void setTileData(World world, BlockPos pos, CompoundNBT data) {
if (data != null) {
public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data, PlayerEntity player) {
if (data != null && AllBlockTags.SAFE_NBT.matches(state)) {
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("y", pos.getY());
data.putInt("z", pos.getZ());

View file

@ -135,7 +135,7 @@ public class BlockzapperItem extends ZapperItem {
blocksnapshot.restore(true, false);
return false;
}
setTileData(world, placed, data);
setTileData(world, placed, state, data, player);
if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) {
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.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@ -36,7 +37,7 @@ public enum TerrainTools {
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) {
case Clear:
targetPositions.forEach(p -> world.setBlockState(p, Blocks.AIR.getDefaultState()));
@ -47,7 +48,7 @@ public enum TerrainTools {
if (!isReplaceable(toReplace))
return;
world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data);
ZapperItem.setTileData(world, p, paintedState, data, player);
});
break;
case Flatten:
@ -67,13 +68,13 @@ public enum TerrainTools {
if (!isReplaceable(toReplace))
return;
world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data);
ZapperItem.setTileData(world, p, paintedState, data, player);
});
break;
case Place:
targetPositions.forEach(p -> {
world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data);
ZapperItem.setTileData(world, p, paintedState, data, player);
});
break;
case Replace:
@ -82,7 +83,7 @@ public enum TerrainTools {
if (isReplaceable(toReplace))
return;
world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data);
ZapperItem.setTileData(world, p, paintedState, data, player);
});
break;
}

View file

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

View file

@ -223,6 +223,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
AxisAlignedBB searchArea =
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)) {
if (!itemEntity.isAlive())
continue;
ItemStack entityItem = itemEntity.getItem();
if (!canAcceptItem(entityItem))
continue;
@ -377,29 +379,6 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
.isHorizontal())
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()))
return false;
@ -418,17 +397,6 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
private boolean handleUpwardOutput(boolean simulate) {
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)
return false;
@ -499,9 +467,12 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
if (world == null)
return LazyOptional.empty();
TileEntity te = world.getTileEntity(pos);
if (te == null
|| (te instanceof ChuteTileEntity) && (side != Direction.DOWN || !(te instanceof SmartChuteTileEntity)))
if (te == null)
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());
}

View file

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

View file

@ -48,6 +48,9 @@ public class ArmInteractionPointHandler {
World world = event.getWorld();
if (!world.isRemote)
return;
PlayerEntity player = event.getPlayer();
if (player != null && player.isSpectator())
return;
ArmInteractionPoint selected = getSelected(pos);
@ -60,7 +63,6 @@ public class ArmInteractionPointHandler {
}
selected.cycleMode();
PlayerEntity player = event.getPlayer();
if (player != null) {
String key = selected.mode == Mode.DEPOSIT ? "mechanical_arm.deposit_to" : "mechanical_arm.extract_from";
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.AllTileEntities;
import com.simibubi.create.content.logistics.block.funnel.FunnelBlock;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
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.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@ -14,8 +13,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
@ -91,10 +88,8 @@ public class ServerSchematicLoader {
}
public void handleNewUpload(ServerPlayerEntity player, String schematic, long size, BlockPos pos) {
String playerPath = getSchematicPath() + "/" + player.getName()
.getFormattedText();
String playerSchematicId = player.getName()
.getFormattedText() + "/" + schematic;
String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName();
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
FilesHelper.createFolderIfMissing(playerPath);
// Unsupported Format
@ -103,6 +98,14 @@ public class ServerSchematicLoader {
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
if (!validateSchematicSizeOnServer(player, size))
return;
@ -118,11 +121,15 @@ public class ServerSchematicLoader {
return;
// Delete schematic with same name
Files.deleteIfExists(Paths.get(getSchematicPath(), playerSchematicId));
Files.deleteIfExists(uploadPath);
// Too many Schematics
Stream<Path> list = Files.list(Paths.get(playerPath));
if (list.count() >= getConfig().maxSchematics.get()) {
long count;
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));
Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f))
.min(Comparator.comparingLong(f -> f.toFile()
@ -132,11 +139,9 @@ public class ServerSchematicLoader {
Files.deleteIfExists(lastFilePath.get());
}
}
list.close();
// Open Stream
OutputStream writer =
Files.newOutputStream(Paths.get(getSchematicPath(), playerSchematicId), StandardOpenOption.CREATE_NEW);
OutputStream writer = Files.newOutputStream(uploadPath);
activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, player.getServerWorld(), pos));
// Notify Tile Entity
@ -165,8 +170,7 @@ public class ServerSchematicLoader {
}
public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) {
String playerSchematicId = player.getName()
.getFormattedText() + "/" + schematic;
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
if (activeUploads.containsKey(playerSchematicId)) {
SchematicUploadEntry entry = activeUploads.get(playerSchematicId);
@ -236,8 +240,7 @@ public class ServerSchematicLoader {
}
public void handleFinishedUpload(ServerPlayerEntity player, String schematic) {
String playerSchematicId = player.getName()
.getFormattedText() + "/" + schematic;
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
if (activeUploads.containsKey(playerSchematicId)) {
try {
@ -258,8 +261,7 @@ public class ServerSchematicLoader {
if (table == null)
return;
table.finishUpload();
table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getName()
.getFormattedText()));
table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getGameProfile().getName()));
} catch (IOException e) {
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,
BlockPos bounds) {
String playerPath = getSchematicPath() + "/" + player.getName()
.getFormattedText();
String playerSchematicId = player.getName()
.getFormattedText() + "/" + schematic;
String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName();
String playerSchematicId = player.getGameProfile().getName() + "/" + schematic;
FilesHelper.createFolderIfMissing(playerPath);
// Unsupported Format
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;
}
@ -288,12 +296,15 @@ public class ServerSchematicLoader {
try {
// Delete schematic with same name
Path path = Paths.get(getSchematicPath(), playerSchematicId);
Files.deleteIfExists(path);
// Too many Schematics
Stream<Path> list = Files.list(Paths.get(playerPath));
if (list.count() >= getConfig().maxSchematics.get()) {
long count;
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));
Optional<Path> lastFilePath = list2.filter(f -> !Files.isDirectory(f))
.min(Comparator.comparingLong(f -> f.toFile()
@ -302,24 +313,17 @@ public class ServerSchematicLoader {
if (lastFilePath.isPresent())
Files.deleteIfExists(lastFilePath.get());
}
list.close();
Template t = new Template();
t.takeBlocksFromWorld(world, pos, bounds, true, Blocks.AIR);
OutputStream outputStream = null;
try {
outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE);
try (OutputStream outputStream = Files.newOutputStream(path)) {
CompoundNBT nbttagcompound = t.writeToNBT(new CompoundNBT());
CompressedStreamTools.writeCompressed(nbttagcompound, outputStream);
player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getName()
.getFormattedText()));
player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getGameProfile().getName()));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null)
IOUtils.closeQuietly(outputStream);
}
} catch (IOException e) {
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) {
AllPackets.channel.sendToServer(ConfigureSchematicannonPacket.setOption(container.getTileEntity()
.getPos(), option, set));
AllPackets.channel.sendToServer(new ConfigureSchematicannonPacket(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.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -466,8 +467,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
CompoundNBT data = null;
if (AllBlockTags.SAFE_NBT.matches(blockState)) {
TileEntity tile = blockReader.getTileEntity(target);
if (tile != null && !tile.onlyOpsCanSetNbt()) {
if (tile != null) {
data = tile.write(new CompoundNBT());
data = NBTProcessors.process(tile, data, true);
}
}
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.simibubi.create.content.schematics.SchematicWorld;
import com.simibubi.create.content.schematics.item.SchematicItem;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.WorldAttached;
import net.minecraft.item.ItemStack;
@ -63,10 +62,6 @@ public class SchematicInstances {
PlacementSettings settings = SchematicItem.getSettings(schematic);
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;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,25 +1,42 @@
package com.simibubi.create.foundation.command;
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.Commands;
import net.minecraft.entity.player.PlayerEntity;
import java.util.Collections;
import java.util.function.Predicate;
public class AllCommands {
public static Predicate<CommandSource> sourceIsPlayer = (cs) -> cs.getEntity() instanceof PlayerEntity;
public static void register(CommandDispatcher<CommandSource> dispatcher) {
dispatcher.register(Commands.literal("create")
LiteralCommandNode<CommandSource> createRoot = dispatcher.register(Commands.literal("create")
//general purpose
.then(ToggleDebugCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
.then(ReplaceInCommandBlocksCommand.register())
.then(HighlightCommand.register())
//dev-util
//Comment out for release
.then(ClearBufferCacheCommand.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;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import com.simibubi.create.Create;
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.gantry.GantryContraptionUpdatePacket;
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.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.sync.*;
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.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.packet.ConfigureFlexcratePacket;
import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket;
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.content.schematics.packet.*;
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.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkDirection;
import net.minecraftforge.fml.network.NetworkEvent.Context;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.fml.network.PacketDistributor.TargetPoint;
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 {
// Client to Server
NBT(NbtPacket.class, NbtPacket::new),
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new),
CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new),
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new),
CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new),
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new),
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new),
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new),
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new),
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new),
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new),
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new),
INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new),
SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new),
LEFT_CLICK(LeftClickPacket.class, LeftClickPacket::new),
NBT(NbtPacket.class, NbtPacket::new, PLAY_TO_SERVER),
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new, PLAY_TO_SERVER),
CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new, PLAY_TO_SERVER),
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new, PLAY_TO_SERVER),
CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new, PLAY_TO_SERVER),
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER),
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER),
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER),
CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new, PLAY_TO_SERVER),
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new, PLAY_TO_SERVER),
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new, PLAY_TO_SERVER),
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new, PLAY_TO_SERVER),
CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new, PLAY_TO_SERVER),
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new, PLAY_TO_SERVER),
MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new, PLAY_TO_SERVER),
INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new, PLAY_TO_SERVER),
SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new, PLAY_TO_SERVER),
LEFT_CLICK(LeftClickPacket.class, LeftClickPacket::new, PLAY_TO_SERVER),
// Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new),
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new),
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new),
CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new),
LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new),
MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new),
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new),
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new),
GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new),
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT),
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new, PLAY_TO_CLIENT),
LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new, PLAY_TO_CLIENT),
MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new, PLAY_TO_CLIENT),
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT),
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 <T extends SimplePacketBase> AllPackets(Class<T> type, Function<PacketBuffer, T> factory) {
packet = new LoadedPacket<>(type, factory);
private <T extends SimplePacketBase> AllPackets(Class<T> type, Function<PacketBuffer, T> factory, NetworkDirection direction) {
packet = new LoadedPacket<>(type, factory, direction);
}
public static void registerPackets() {
channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
.serverAcceptedVersions(s -> true)
.clientAcceptedVersions(s -> true)
.serverAcceptedVersions(NETWORK_VERSION::equals)
.clientAcceptedVersions(NETWORK_VERSION::equals)
.networkProtocolVersion(() -> NETWORK_VERSION)
.simpleChannel();
for (AllPackets packet : values())
@ -117,16 +114,18 @@ public enum AllPackets {
Function<PacketBuffer, T> decoder;
BiConsumer<T, Supplier<Context>> handler;
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;
decoder = factory;
handler = T::handle;
this.type = type;
this.direction = direction;
}
private void register() {
channel.messageBuilder(type, index++)
channel.messageBuilder(type, index++, direction)
.encoder(encoder)
.decoder(decoder)
.consumer(handler)

View file

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

View file

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

View file

@ -28,7 +28,7 @@ public class LinkHandler {
PlayerEntity player = event.getPlayer();
Hand hand = event.getHand();
if (player.isSneaking())
if (player.isSneaking() || player.isSpectator())
return;
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.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
@ -21,17 +20,10 @@ import net.minecraft.nbt.CompoundNBT;
public class FilesHelper {
public static void createFolderIfMissing(String name) {
Path path = Paths.get(name);
if (path.getParent() != null)
createFolderIfMissing(path.getParent()
.toString());
if (!Files.isDirectory(path)) {
try {
Files.createDirectory(path);
Files.createDirectories(Paths.get(name));
} 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;
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.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox;
import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline;
import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import java.util.*;
public class Outliner {
final Map<Object, OutlineEntry> outlines;
@ -57,6 +51,13 @@ public class Outliner {
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) {
createAABBOutlineIfMissing(slot, bb);
ChasingAABBOutline outline = getAndRefreshAABB(slot);
@ -112,6 +113,12 @@ public class Outliner {
return (ChasingAABBOutline) entry.getOutline();
}
private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) {
OutlineEntry entry = outlines.get(slot);
entry.ticksTillRemoval = ttl;
return (ChasingAABBOutline) entry.getOutline();
}
// Maintenance
public Outliner() {

View file

@ -6,6 +6,7 @@ import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@ -22,6 +23,11 @@ import java.util.stream.Collectors;
@MethodsReturnNonnullByDefault
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,
* 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);
}
/*@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) {
return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis);
}

View file

@ -1,15 +1,26 @@
package com.simibubi.create.foundation.utility.placement;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
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.BlockRayTraceResult;
import net.minecraft.util.math.Vec3i;
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;
@ -56,24 +67,48 @@ public class PlacementOffset {
return world.getBlockState(new BlockPos(pos)).getMaterial().isReplaceable();
}
public void placeInWorld(World world, BlockItem blockItem, PlayerEntity player, ItemStack item) {
placeInWorld(world, blockItem.getBlock().getDefaultState(), player, item);
}
public ActionResultType placeInWorld(World world, BlockItem blockItem, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
public void placeInWorld(World world, BlockState defaultState, PlayerEntity player, ItemStack item) {
if (world.isRemote)
return;
ItemUseContext context = new ItemUseContext(player, hand, ray);
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)) {
IFluidState fluidState = world.getFluidState(newPos);
state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER);
}
BlockSnapshot snapshot = BlockSnapshot.getBlockSnapshot(world, newPos);
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())
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.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.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress",

View file

@ -1,5 +1,4 @@
{
"_": "->------------------------] Game Elements [------------------------<-",
"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_repeater": "Répéteur réglable",
"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_slab": "Dalle 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_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_slab": "Dalles 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_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_pillar": "Pilier en andésite",
"block.create.andesite_tunnel": "Tunnel en andésite",
"block.create.basin": "Bassin",
"block.create.belt": "Tapis roulant",
"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.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.clutch": "Embrayage",
"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_casing": "Boîtier en cuivre",
"block.create.copper_casing": "Revêtement en cuivre",
"block.create.copper_ore": "Minerai 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_fluid_tank": "Réservoir créatif",
"block.create.creative_motor": "Moteur",
"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.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_bricks": "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_wall": "Muret de briques de scorie sombre",
"block.create.dark_scoria_cobblestone": "Pierres de scorie sombre",
"block.create.deployer": "Déployeur",
"block.create.depot": "Dépot",
"block.create.diorite_bricks": "Briques de diorite",
"block.create.dolomite": "Dolomie",
"block.create.dolomite_bricks": "Briques de dolomie",
"block.create.dolomite_bricks_slab": "Dalle de briques de dolomie",
"block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomie",
"block.create.dolomite_bricks_wall": "Muret de briques de dolomie",
"block.create.dolomite_pillar": "Pillier de dolomie",
"block.create.encased_fan": "Ventilateur enfermé",
"block.create.dolomite": "Dolomite",
"block.create.dolomite_bricks": "Briques de dolomite",
"block.create.dolomite_bricks_slab": "Dalle de briques de dolomite",
"block.create.dolomite_bricks_stairs": "Escaliers de briques de dolomite",
"block.create.dolomite_bricks_wall": "Muret de briques de dolomite",
"block.create.dolomite_pillar": "Pillier de dolomite",
"block.create.encased_chain_drive": "Chaine de transmission",
"block.create.encased_fan": "Ventilateur enchâssé",
"block.create.flywheel": "Volant d'inertie",
"block.create.framed_glass": "Grande fenêtre en verre",
"block.create.framed_glass_pane": "Grande vitre encadrée",
@ -85,23 +123,23 @@
"block.create.mechanical_saw": "Scie mécanique",
"block.create.natural_scoria": "Scorie naturelle",
"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_dolomite": "Dolomie polie",
"block.create.polished_dolomite": "Dolomite polie",
"block.create.polished_gabbro": "Gabbro poli",
"block.create.polished_limestone": "Calcaire poli",
"block.create.polished_limestone_slab": "Dalle de calcaire polie",
"block.create.polished_scoria": "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_slab": "Dalle de calcaire patinées",
"block.create.polished_weathered_limestone": "Calcaire altéré polies",
"block.create.polished_weathered_limestone_slab": "Dalle de calcaire altéré",
"block.create.portable_storage_interface": "Interface de stockage portable",
"block.create.powered_latch": "Verrou alimenté",
"block.create.powered_toggle_latch": "Verrou alimenté à bascule",
"block.create.pulley_magnet": "Aimant de poulie",
"block.create.pulse_repeater": "Répéteur d'impulsions",
"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.rope": "Corde",
"block.create.rope_pulley": "Poulie à corde",
@ -112,7 +150,7 @@
"block.create.scoria_bricks": "Briques de scorie",
"block.create.scoria_pillar": "Pillier de scorie",
"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.sticky_mechanical_piston": "Piston mécanique collant",
"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_pane": "Vitre encadrée verticale",
"block.create.water_wheel": "Roue à eau",
"block.create.weathered_limestone": "Calcaire patinées",
"block.create.weathered_limestone_bricks": "Briques de calcaire patinées",
"block.create.weathered_limestone_bricks_slab": "Dalle de briques de calcaire patinées",
"block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de calcaire patinées",
"block.create.weathered_limestone_bricks_wall": "Muret de briques de calcaire patinées",
"block.create.weathered_limestone_pillar": "Pillier de calcaire patinées",
"block.create.weathered_limestone": "Calcaire altéré",
"block.create.weathered_limestone_bricks": "Briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_slab": "Dalle de briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_stairs": "Escaliers de briques de Calcaire altéré",
"block.create.weathered_limestone_bricks_wall": "Muret de briques de Calcaire altéré",
"block.create.weathered_limestone_pillar": "Pillier de Calcaire altéré",
"block.create.zinc_block": "Bloc de zinc",
"block.create.zinc_ore": "Minerai de zinc",
@ -203,7 +241,7 @@
"item.create.schematic_and_quill": "Schéma et plume",
"item.create.shadow_steel": "Acier sombre",
"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.wand_of_symmetry": "Bâton de symétrie",
"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.its_alive": "Ça bouge!",
"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.overstressed": "Surtension",
"advancement.create.overstressed.desc": "Testez d'abord les limites de la force mécanique",
@ -237,7 +275,7 @@
"itemGroup.create.base": "Create",
"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_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",
@ -365,10 +403,10 @@
"create.contraptions.movement_mode": "Mode de mouvement",
"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_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_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.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.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.slime_added": "Bruit de slime",
"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.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.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.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.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.control1": "Clic droit au sol",
"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.action3": "Ouvre l'_interface_ _de_ _configuration_",
"item.create.tree_fertilizer.tooltip": "ENGRAIS POUR ARBRE",
"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.condition1": "Lorsqu'utilisé sur une pousse d'arbre",
"item.create.tree_fertilizer.tooltip.behaviour1": "Fait pousser des arbres _indépendamment_ de leurs _conditions_ _d'emplacement_",
"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'rotors communs.",
"item.create.tree_fertilizer.tooltip.condition1": "Lorsqu'utilisé sur une pousse d'rotor",
"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.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.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.condition2": "Clic droit",
"item.create.filter.tooltip.behaviour2": "Ouvre l'_interface_ _de_ _configuration_.",
"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.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.condition2": "Clic droit",
"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.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.control1": "Clic droit en étant accroupi",
"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.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.shaft.tooltip": "ARBRE MÉCANIQUE",
"block.create.shaft.tooltip.summary": "_Relais_ la _rotation_ en ligne droite.",
"block.create.shaft.tooltip": "ROTOR",
"block.create.shaft.tooltip.summary": "_Relaie_ la _rotation_ en ligne droite.",
"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.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.summary": "_Relais_ la _rotation_ en ligne droite. Convient pour propager la rotation à travers les murs.",
"block.create.encased_shaft.tooltip": "ROTOR ENCASTRÉ",
"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.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.summary": "Une commande pour basculer le sens de rotation des arbres connectés.",
"block.create.gearshift.tooltip": "BOÎTE DE VITESSES",
"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.behaviour1": "_Inverse_ la rotation sortante.",
"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.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.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.control1": "Clic droit sur arbre",
"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.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 rotor",
"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.action2": "_Réinitialise_ la première position sélectionnée pour le tapis roulant.",
"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.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.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.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.control1": "Clic droit a kinetic block",
"item.create.wrench.tooltip.action1": "_Tourne_ les _composents_ proche ou loin de la face avec lequel vous avez interagi.",
"item.create.wrench.tooltip.control1": "Clic droit sur un bloc de Create",
"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.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.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.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.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.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.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.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.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.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.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.mechanical_press.tooltip": "PRESSE MÉCANIQUE",
@ -814,11 +852,11 @@
"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.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.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.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.",
@ -838,7 +876,7 @@
"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.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",
@ -848,17 +886,17 @@
"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.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.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.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.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.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.",
@ -866,48 +904,50 @@
"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.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.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.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.condition2": "Clic droit",
"block.create.sequenced_gearshift.tooltip.behaviour2": "Ouvre _l'interface_ _de_ _configuration_",
"block.create.cart_assembler.tooltip": "ASSEMBLEUR DE CHARIOT",
"block.create.cart_assembler.tooltip.summary": "Monte une structure connectée sur un _chariot_ _passant_.",
"block.create.cart_assembler.tooltip": "ASSEMBLEUR DE WAGON",
"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.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.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.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.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.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.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.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.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.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.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.condition2": "Lorsqu'en mouvement",
"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.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.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.condition1": "Lorsque 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.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": "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. 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.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.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.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.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.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.condition1": "Lorsqu'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": "LIEN DE REDSTONE",
"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": "Quand alimenté",
"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.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.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.summary": "N'émet de l'énergie que par paires. Il est mobile avec _pistons_ _mécaniques_ ou _roulements_.",
"block.create.redstone_contact.tooltip.condition1": "Lorsque tourné vers un autre redstone_contact",
"block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ _redstone_.",
"block.create.redstone_contact.tooltip.condition2": "Lorsqu'en mouvement",
"block.create.redstone_contact.tooltip.behaviour2": "Déclenche tous les redstone_contacts fixes qu'il passe.",
"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 des _pistons_ _mécaniques_ ou _roulements_.",
"block.create.redstone_contact.tooltip.condition1": "Quand tourné vers un autre contact de redstone",
"block.create.redstone_contact.tooltip.behaviour1": "Fournit un _signal_ de _redstone_.",
"block.create.redstone_contact.tooltip.condition2": "Quand en mouvement",
"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.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.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.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.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.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.summary": "Boîtier de machine robuste avec une variété d'utilisations. Sans danger pour la décoration.",
"block.create.brass_casing.tooltip": "REVÊTEMENT EN LAITON",
"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.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.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.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.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.",
"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.summary": "Un matériau chromatique forgé à partir de _lumière_ _absorbée_.",
"item.create.shadow_steel.tooltip": "ACIER SOMBRE",
"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.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.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.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.randomWipDescription5": "Croyez-moi, c'est inutile.",
"create.tooltip.randomWipDescription6": "En utilisant cet article, vous êtes responsables et acceptez ses conditions.",