diff --git a/build.gradle b/build.gradle index c91419525c..4ad56f59ff 100644 --- a/build.gradle +++ b/build.gradle @@ -413,7 +413,7 @@ project(":annotations"){ dependencies{ implementation 'com.squareup:javapoet:1.12.1' - implementation "com.github.Anuken.Arc:arc-core:$arcHash" + implementation arcModule("arc-core") } } diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 044d48dcaf..f9d668db70 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1081,7 +1081,7 @@ setting.backgroundpause.name = Pause In Background setting.buildautopause.name = Auto-Pause Building setting.doubletapmine.name = Double-Tap to Mine setting.commandmodehold.name = Hold For Command Mode -setting.distinctcontrolgroups.name = Limit One Control Group Per Unit +setting.distinctcontrolgroups.name = Limit One Control Group Per Unit setting.modcrashdisable.name = Disable Mods On Startup Crash setting.animatedwater.name = Animated Surfaces setting.animatedshields.name = Animated Shields diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 6a2f847786..6c4629d828 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -35,7 +35,7 @@ load.mod = Mods load.scripts = Scripts be.update = Une nouvelle version expérimentale est disponible: -be.update.confirm = Télécharger et Redémarrer le jeu maintenant ? +be.update.confirm = Télécharger et redémarrer le jeu maintenant ? be.updating = Mise à jour en cours... be.ignore = Ignorer be.noupdates = Aucune mise à jour trouvée. @@ -72,7 +72,7 @@ schematic.saved = Schéma enregistré. schematic.delete.confirm = Ce schéma sera supprimé définitivement ! schematic.edit = Editer Schéma schematic.info = {0}x{1}, {2} blocs -schematic.disabled = [scarlet]Schémas désactivés ![]\nVous n'êtes pas autorisés à utiliser des schémas sur cette [accent]carte[] ou dans ce [accent]serveur. +schematic.disabled = [scarlet]Schémas désactivés ![]\nVous n'êtes pas autorisé à utiliser des schémas sur cette [accent]carte[] ou dans ce [accent]serveur. schematic.tags = Étiquettes : schematic.edittags = Éditer les étiquettes schematic.addtag = Ajouter une étiquette @@ -129,7 +129,7 @@ committingchanges = Validation des modifications done = Terminé feature.unsupported = Votre appareil ne prend pas en charge cette fonctionnalité. -mods.initfailed = [red]⚠[] L'instance précédente de Mindustry n’a pas pu s’initialiser. Cela a probablement été causé par des mods.\n\nPour éviter une boucle de crash, [red]tous les mods ont été désactivés.[] +mods.initfailed = [red]⚠[] L'instance précédente de Mindustry n’a pas pu s’initialiser. Cela a probablement été causé par des mods.\n\nPour éviter une boucle de plantage, [red]tous les mods ont été désactivés.[] mods = Mods mods.none = [lightgray]Aucun Mod trouvé ! mods.guide = Guide de Modding @@ -245,7 +245,7 @@ hosts.none = [lightgray]Aucune partie en LAN trouvée ! host.invalid = [scarlet]Impossible de se connecter à l'hôte. servers.local = Serveurs locaux -servers.local.steam = Jeux Libres & Serveurs Locaux +servers.local.steam = Parties Libres & Serveurs Locaux servers.remote = Serveurs distants servers.global = Serveurs communautaires @@ -291,7 +291,7 @@ confirmunban = Êtes-vous sûr de vouloir annuler le ban de ce joueur ? confirmadmin = Êtes-vous sûr de vouloir faire de "{0}[white]" un administrateur ? confirmunadmin = Êtes-vous sûr de vouloir supprimer le statut d'administrateur de "{0}[white]" ? votekick.reason = Raison du vote d'expulsion -votekick.reason.message = Êtes-vous sûr de vouloir voter l'expulsion de "{0}[white]"?Si oui, merci d'entrer la raison : +votekick.reason.message = Êtes-vous sûr de vouloir voter l'expulsion de "{0}[white]"?\nSi oui, merci d'entrer la raison : joingame.title = Rejoindre une partie joingame.ip = Adresse IP : disconnect = Déconnecté. @@ -354,23 +354,23 @@ command.rebuild = Reconstruire command.assist = Assister command.move = Bouger command.boost = Booster -command.enterPayload = Enter Payload Block -command.loadUnits = Load Units -command.loadBlocks = Load Blocks -command.unloadPayload = Unload Payload -stance.stop = Cancel Orders -stance.shoot = Stance: Shoot -stance.holdfire = Stance: Hold Fire -stance.pursuetarget = Stance: Pursue Target -stance.patrol = Stance: Patrol Path -stance.ram = Stance: Ram\n[lightgray]Straight line movement, no pathfinding +command.enterPayload = Entrer dans Bloc de Transport +command.loadUnits = Transporter Unités +command.loadBlocks = Transporter Blocs +command.unloadPayload = Poser Chargement +stance.stop = Annuler les Ordres +stance.shoot = Ordre: Tirer +stance.holdfire = Ordre: Ne pas Tirer +stance.pursuetarget = Ordre: Poursuivre Cible +stance.patrol = Ordre: Chemins de Contrôle +stance.ram = Ordre: Charger\n[lightgray]Mouvement en ligne droite, sans détection de chemins openlink = Ouvrir le lien copylink = Copier le lien back = Retour max = Max objective = Objectif de la Carte crash.export = Exporter les rapports de bugs -crash.none = Aucun rapport de bug trouvé. +crash.none = Aucun rapport de bugs trouvé. crash.exported = Rapports de bugs exportés. data.export = Exporter les données data.import = Importer des données @@ -431,7 +431,7 @@ steam.error = Échec d'initialisation des services Steam.\nErreur : {0} editor.planet = Planète : editor.sector = Secteur : editor.seed = Graine : -editor.cliffs = Transformer murs en falaises +editor.cliffs = Transformer les murs en falaises editor.brush = Pinceau editor.openin = Ouvrir dans l'éditeur editor.oregen = Génération de minerai @@ -564,7 +564,7 @@ toolmode.fillerase = Remplir et effacer toolmode.fillerase.description = Efface les blocs\ndu même type. toolmode.drawteams = Dessiner les équipes toolmode.drawteams.description = Change les équipes\nau lieu de blocs. -#unitilisé +#inutilisé toolmode.underliquid = Sous les liquides toolmode.underliquid.description = Dessiner les sols sous les tuiles de liquides. @@ -664,7 +664,7 @@ marker.shapetext.name = Forme de Texte marker.minimap.name = Minicarte marker.shape.name = Forme marker.text.name = Texte -marker.line.name = Line +marker.line.name = Ligne marker.background = Fond marker.outline = Contour @@ -707,7 +707,7 @@ connectfail = [scarlet]Échec de la connexion au serveur : \n\n[accent]{0} error.unreachable = Serveur inaccessible.\nEst-ce que l'adresse est écrite correctement? error.invalidaddress = Adresse invalide. error.timedout = Expiration du délai!\nAssurez-vous que l'ouverture des ports est configurée chez l'hôte, que le serveur est ouvert et que l'adresse est correcte! -error.mismatch = Erreur de paquet :\nPossible incompatibilité de version client/serveur.\nAssurez-vous que l'hôte et vous disposez de la même version de Mindustry ! +error.mismatch = Erreur de paquet :\nPossible incompatibilité de version client/serveur.\nAssurez-vous que l'hôte et vous, disposez de la même version de Mindustry ! error.alreadyconnected = Déjà connecté. error.mapnotfound = Fichier de carte introuvable ! error.io = Erreur de Réseau (I/O) @@ -752,12 +752,12 @@ sector.curlost = Secteur perdu sector.missingresources = [scarlet]Ressources du Noyau insuffisantes ! sector.attacked = Secteur [accent]{0}[white] attaqué ! sector.lost = Secteur [accent]{0}[white] perdu ! -#note: the missing space in the line below is intentional +#note: l'espace manquant dans la ligne ci-dessous est intentionnel sector.captured = Secteur [accent]{0}[white]capturé ! sector.changeicon = Changer l'Icône sector.noswitch.title = Impossible de changer de Secteur sector.noswitch = Vous ne pouvez pas changer de secteur pendant qu’un autre est attaqué.\n\nSecteur: [accent]{0}[] sur [accent]{1}[] -sector.view = Voir le Secteur +sector.view = Voir le secteur threat.low = Faible threat.medium = Normale @@ -873,7 +873,7 @@ settings.graphics = Graphismes settings.cleardata = Effacer les données du jeu... settings.clear.confirm = Êtes-vous sûr de vouloir effacer ces données?\nAucun retour en arrière n'est possible ! settings.clearall.confirm = [scarlet]ATTENTION ![]\nCette action effacera toutes les données, y compris les sauvegardes, les cartes, la progression et la configuration des touches.\nUne fois que vous aurez pressé 'OK', le jeu effacera TOUTES les données et se fermera. -settings.clearsaves.confirm = Êtes-vous sûr de vouloir supprimer toutes vos sauvegardes? +settings.clearsaves.confirm = Êtes-vous sûr de vouloir supprimer toutes vos sauvegardes ? settings.clearsaves = Supprimer les Sauvegardes settings.clearresearch = Supprimer la Recherche settings.clearresearch.confirm = Êtes-vous sûr de vouloir supprimer toutes les recherches de la campagne ? @@ -938,7 +938,7 @@ stat.maxunits = Max d'Unités Actives stat.health = Santé stat.armor = Armure stat.buildtime = Durée de construction -stat.maxconsecutive = Max Consécutif +stat.maxconsecutive = Max consécutif stat.buildcost = Coût de construction stat.inaccuracy = Imprécision stat.shots = Tirs @@ -983,9 +983,9 @@ ability.movelightning = Déplacement éclair ability.shieldarc = Arc de Bouclier ability.suppressionfield = Champ de Suppression de Soins ability.energyfield = Champ d'énergie -ability.energyfield.sametypehealmultiplier = [lightgray]Same Type Healing: [white]{0}% -ability.energyfield.maxtargets = [lightgray]Max Targets: [white]{0} -ability.regen = Regeneration +ability.energyfield.sametypehealmultiplier = [lightgray]Soins des Unités du Même Type: [white]{0}% +ability.energyfield.maxtargets = [lightgray]Cibles Maximales: [white]{0} +ability.regen = Régénération bar.onlycoredeposit = Seul le dépôt de ressources dans le Noyau est autorisé bar.drilltierreq = Meilleure Foreuse Requise @@ -1025,7 +1025,7 @@ bullet.splashdamage = [stat]{0}[lightgray] dégâts de zone ~[stat] {1}[lightgra bullet.incendiary = [stat]incendiaire bullet.homing = [stat]autoguidé bullet.armorpierce = [stat]perceur d'armure -bullet.maxdamagefraction = [stat]{0}%[lightgray] damage limit +bullet.maxdamagefraction = [stat]{0}%[lightgray] limite de dégâts bullet.suppression = [stat]{0} sec[lightgray] suppression de soins ~ [stat]{1}[lightgray] blocs bullet.interval = [stat]{0}/sec[lightgray] Balle secondaire: bullet.frags = [stat]{0}[lightgray]x Balle à fragmentation: @@ -1081,12 +1081,12 @@ setting.backgroundpause.name = Pause en Arrière-plan setting.buildautopause.name = Confirmation avant construction setting.doubletapmine.name = Double-clic pour Miner setting.commandmodehold.name = Retenir pour le Mode « Commande » -setting.distinctcontrolgroups.name = Limit One Control Group Per Unit +setting.distinctcontrolgroups.name = Limiter un groupe de contrôle par unité setting.modcrashdisable.name = Désactiver les mods lors d'un crash au démarrage setting.animatedwater.name = Surfaces Animées setting.animatedshields.name = Boucliers Animés -setting.playerindicators.name = Indicateurs alliés -setting.indicators.name = Indicateurs ennemis +setting.playerindicators.name = Indicateurs d'alliés +setting.indicators.name = Indicateurs d'ennemis setting.autotarget.name = Visée automatique setting.keyboard.name = Contrôles Souris+Clavier setting.touchscreen.name = Commandes d'écran tactile @@ -1117,7 +1117,7 @@ setting.fullscreen.name = Plein Écran setting.borderlesswindow.name = Fenêtré sans bordures setting.borderlesswindow.name.windows = Plein écran sans bordure setting.borderlesswindow.description = Un redémarrage peut être nécessaire pour appliquer les changements. -setting.fps.name = Afficher FPS et Ping +setting.fps.name = Afficher les FPS et le Ping setting.console.name = Activer la Console setting.smoothcamera.name = Lissage de la Caméra setting.vsync.name = Synchronisation Verticale @@ -1127,8 +1127,8 @@ setting.coreitems.name = Afficher les objets du Noyau setting.position.name = Afficher la position du joueur setting.mouseposition.name = Afficher la Position de la Souris setting.musicvol.name = Volume de la Musique -setting.atmosphere.name = Montrer l'Atmosphère de la planète -setting.drawlight.name = Draw Darkness/Lighting +setting.atmosphere.name = Montrer l'Atmosphère des planètes +setting.drawlight.name = Dessiner les Ombres/Lumières setting.ambientvol.name = Volume Ambiant setting.mutemusic.name = Couper la Musique setting.sfxvol.name = Volume des Sons et Effets @@ -1155,7 +1155,7 @@ keybind.title = Paramètres des Touches du Clavier keybinds.mobile = [scarlet]La plupart des touches de clavier ne sont pas fonctionnelles sur mobile. Seuls les mouvements basiques sont supportés. category.general.name = Général category.view.name = Vue -category.command.name = Unit Command +category.command.name = Commandes d'Unité category.multiplayer.name = Multijoueur category.blocks.name = Sélection des blocs placement.blockselectkeys = \n[lightgray]Raccourci : [{0}, @@ -1173,23 +1173,26 @@ keybind.mouse_move.name = Suivre la souris keybind.pan.name = Vue Panoramique keybind.boost.name = Boost keybind.command_mode.name = Mode « Commande » -keybind.command_queue.name = Unit Command Queue -keybind.create_control_group.name = Create Control Group -keybind.cancel_orders.name = Cancel Orders -keybind.unit_stance_shoot.name = Unit Stance: Shoot -keybind.unit_stance_hold_fire.name = Unit Stance: Hold Fire -keybind.unit_stance_pursue_target.name = Unit Stance: Pursue Target -keybind.unit_stance_patrol.name = Unit Stance: Patrol -keybind.unit_stance_ram.name = Unit Stance: Ram -keybind.unit_command_move = Unit Command: Move -keybind.unit_command_repair = Unit Command: Repair -keybind.unit_command_rebuild = Unit Command: Rebuild -keybind.unit_command_assist = Unit Command: Assist -keybind.unit_command_mine = Unit Command: Mine -keybind.unit_command_boost = Unit Command: Boost -keybind.unit_command_load_units = Unit Command: Load Units -keybind.unit_command_load_blocks = Unit Command: Load Blocks -keybind.unit_command_unload_payload = Unit Command: Unload Payload +keybind.command_queue.name = File d'attente des Commandes d'Unités +keybind.create_control_group.name = Créer un Groupe de Contrôle +keybind.cancel_orders.name = Annuler les Ordres + +keybind.unit_stance_shoot.name = Ordre: Tirer +keybind.unit_stance_hold_fire.name = Ordre: Ne pas tirer +keybind.unit_stance_pursue_target.name = Ordre: Poursuivre la cible +keybind.unit_stance_patrol.name = Ordre: Patrouille +keybind.unit_stance_ram.name = Ordre: Charger + +keybind.unit_command_move = Commande: Bouger +keybind.unit_command_repair = Commande: Réparer +keybind.unit_command_rebuild = Commande: Reconstruire +keybind.unit_command_assist = Commande: Assister +keybind.unit_command_mine = Commande: Miner +keybind.unit_command_boost = Commande: Boost +keybind.unit_command_load_units = Commande: Transporter unités +keybind.unit_command_load_blocks = Commande: Transporter blocs +keybind.unit_command_unload_payload = Commande: Poser chargement + keybind.rebuild_select.name = Reconstruire la Zone keybind.schematic_select.name = Sélectionner une Région keybind.schematic_menu.name = Menu des schémas @@ -1222,7 +1225,7 @@ keybind.deselect.name = Désélectionner keybind.pickupCargo.name = Prendre un Chargement keybind.dropCargo.name = Lâcher un Chargement keybind.shoot.name = Tirer -keybind.zoom.name = Zoom +keybind.zoom.name = Zoomer keybind.menu.name = Menu keybind.pause.name = Pause keybind.pause_building.name = Pauser/Reprendre la Construction @@ -1240,9 +1243,9 @@ keybind.chat_history_prev.name = Remonter l'Historique du Tchat keybind.chat_history_next.name = Descendre l'Historique du Tchat keybind.chat_scroll.name = Défilement du Tchat keybind.chat_mode.name = Changer le mode du Tchat -keybind.drop_unit.name = Larguer une unité +keybind.drop_unit.name = Larguer une Unité keybind.zoom_minimap.name = Zoomer la Mini-carte -mode.help.title = Description des modes de jeu +mode.help.title = Description des modes de jeux mode.survival.name = Survie mode.survival.description = Le mode normal. Ressources limitées et vagues automatiques.\n[gray]Requiert des points d'apparition ennemis pour pouvoir jouer à ce mode. mode.sandbox.name = Bac à Sable @@ -1253,12 +1256,12 @@ mode.pvp.description = Lutter contre d'autres joueurs pour gagner !\n[gray]Requi mode.attack.name = Attaque mode.attack.description = Pas forcément de vagues, le but étant de détruire la base ennemie.\n[gray]Requiert un Noyau rouge pour jouer à ce mode. mode.custom = Règles Personnalisées -rules.invaliddata = Invalid clipboard data. -rules.hidebannedblocks = Cacher les blocs bannis. +rules.invaliddata = Données du Presse-Papier Invalides. +rules.hidebannedblocks = Cacher les blocs bannis. rules.infiniteresources = Ressources Infinies -rules.onlydepositcore = Seulement autoriser le Dépôt d'Objets dans le Noyau -rules.derelictrepair = Allow Derelict Block Repair +rules.onlydepositcore = Seulement autoriser le dépôt d'Objets dans le Noyau +rules.derelictrepair = Autoriser la réparation des structures abandonnées rules.reactorexplosions = Explosion des Réacteurs rules.coreincinerates = Incinération des surplus du Noyau rules.disableworldprocessors = Désactiver les Processeurs Globaux @@ -1275,7 +1278,7 @@ rules.rtsmaxsquadsize = Taille Maximale d'une Escouade rules.rtsminattackweight = Poids Minimum d'une Attaque rules.cleanupdeadteams = Détruire les structures des équipes vaincues (JcJ) rules.corecapture = Capture du Noyau lors de sa Destruction -rules.polygoncoreprotection = Protection Polygonale du Noyau +rules.polygoncoreprotection = Protection polygonale du Noyau rules.placerangecheck = Vérification de la Portée de Placement rules.enemyCheat = Ressources infinies pour l'IA (équipe rouge) rules.blockhealthmultiplier = Multiplicateur de Santé des Blocs @@ -1287,9 +1290,9 @@ rules.unitdamagemultiplier = Multiplicateur de Dégât des Unités rules.unitcrashdamagemultiplier = Multiplicateur de Dégât de chute des Unités rules.solarmultiplier = Multiplicateur de l'Efficacité des Panneaux Solaires rules.unitcapvariable = Les Noyaux contribuent à la limite d'Unités actives -rules.unitcap = Limite d'Unités actives de Base -rules.limitarea = Limite de la Zone de Jeu de la Carte -rules.enemycorebuildradius = Périmètre de Non-Construction autour du Noyau ennemi :[lightgray] (blocs) +rules.unitcap = Limite initiale d'Unités actives +rules.limitarea = Limite de la zone de jeu de la Carte +rules.enemycorebuildradius = Périmètre Non-Constructible autour du Noyau ennemi :[lightgray] (blocs) rules.wavespacing = Temps entre les Vagues :[lightgray] (sec) rules.initialwavespacing = Temps de Vague Initial :[lightgray] (sec) rules.buildcostmultiplier = Multiplicateur du prix de construction @@ -1297,7 +1300,7 @@ rules.buildspeedmultiplier = Multiplicateur du temps de construction rules.deconstructrefundmultiplier = Multiplicateur du remboursement lors de la déconstruction rules.waitForWaveToEnd = Les Vagues attendent la mort des ennemis rules.wavelimit = La Partie termine après la Vague -rules.dropzoneradius = Rayon d'Apparition des ennemis :[lightgray] (blocs) +rules.dropzoneradius = Rayon de la Zone d'Apparition ennemie :[lightgray] (blocs) rules.unitammo = Les Unités nécessitent des munitions rules.enemyteam = Équipe ennemie rules.playerteam = Équipe du joueur @@ -1650,9 +1653,9 @@ block.large-constructor.description = Fabrique des structures d'une taille maxim block.deconstructor.name = Déconstructeur block.deconstructor.description = Déconstruit les structures et les unités. Retourne 100% du coût de construction. block.payload-loader.name = Chargeur de charge utile -block.payload-loader.description = Chargez les liquides et les articles dans les blocs. +block.payload-loader.description = Charge les liquides et les ressources dans les blocs. block.payload-unloader.name = Déchargeur de charge utile -block.payload-unloader.description = Décharge les liquides et les articles des blocs. +block.payload-unloader.description = Décharge les liquides et les ressources des blocs. block.heat-source.name = Source de Chaleur block.heat-source.description = Produit de grandes quantités de chaleur. Bac à sable uniquement. @@ -1840,11 +1843,11 @@ hint.research = Utilisez le bouton \ue875 [accent]Recherche[] pour rechercher de hint.research.mobile = Utilisez le bouton \ue875 [accent]Recherche[] dans le \ue88c [accent]Menu[] pour rechercher de nouvelles technologies. hint.unitControl = Retenez [accent][[Ctrl-gauche][] et [accent]cliquez[] pour contrôler une tourelle ou une unité alliée. hint.unitControl.mobile = [accent][[Tapez][] 2 fois une tourelle ou une unité alliée pour la contrôler. -hint.unitSelectControl = Pour contrôler les unités, entrez en mode [accent]« Commande »[] en pressant [accent]Maj gauche.[]\nEn mode « Commande », cliquez et faites glisser la souris pour sélectionner des unités. Faites un [accent]Clic droit[] à un emplacement ou une cible pour que les unités s'y déplacent. +hint.unitSelectControl = Pour contrôler les unités, entrez en mode [accent]« Commande »[] en pressant [accent]Maj gauche[].\nEn mode « Commande », cliquez et faites glisser la souris pour sélectionner des unités. Faites un [accent]Clic droit[] à un emplacement ou une cible pour que les unités s'y déplacent. hint.unitSelectControl.mobile = Pour contrôler les unités, entrez en mode [accent]« Commande »[] en pressant le bouton de [accent]commande[] en bas à gauche de l'écran.\nEn mode « Commande », pressez longuement et faites glisser pour sélectionner des unités. Tapez un emplacement ou une cible pour que les unités s'y déplacent. hint.launch = Une fois que vous avez collecté assez de ressources, vous pouvez [accent]Lancer[] votre Noyau en sélectionnant un secteur depuis la \ue827 [accent]Carte[] en bas à droite. hint.launch.mobile = Une fois que vous avez collecté assez de ressources, vous pouvez [accent]Lancer[] votre Noyau en sélectionnant un secteur depuis la \ue827 [accent]Carte[] dans le \ue88c [accent]Menu[]. -hint.schematicSelect = Retenez [accent][[F][] pour sélectionner des blocs dans une zone afin de les copier et les coller.\n\n[accent][[Clic du milieu][] pour copier un seul type de bloc. +hint.schematicSelect = Retenez [accent][[F][] pour sélectionner des blocs dans une zone afin de les copier et les coller.\n\n[accent][[Clic molette][] pour copier un seul type de bloc. hint.rebuildSelect = Retenez [accent][[B][] et faites glissez pour selectionner les plans des blocs détruits.\nCela va automatiquement les reconstruire. hint.rebuildSelect.mobile = Selectionnez le \ue874 bouton de copie, ensuite tapez le \ue80f bouton de reconstruction et faites glisser pour sélectionner les plans des blocs détruits.\nCela va les reconstruire automatiquement. hint.conveyorPathfind = Retenez [accent][[Ctrl-gauche][] pendant que vous placez des convoyeurs, afin de générer un chemin automatiquement. @@ -1860,7 +1863,7 @@ hint.guardian = Les [accent]Gardiens[] sont protégés par un bouclier. Les muni hint.coreUpgrade = Les Noyaux peuvent être améliorés [accent]en plaçant un Noyau de plus haut niveau sur eux[].\n\nPlacez un \uf868 Noyau [accent]Fondation[] sur le \uf869 Noyau [accent]Fragment[]. Soyez sûrs que rien n'obstrue la construction. hint.presetLaunch = Les [accent]secteurs[] gris, tels que [accent]Frozen Forest[], peuvent être lancés de n'importe où. Ils ne requièrent pas la capture d'un secteur adjacent.\n\n[accent]Il y a beaucoup de secteurs[] comme celui-ci, qui sont [accent]optionnels[]. hint.presetDifficulty = Ce secteur a un niveau de menace ennemi [scarlet]élevé[].\nIl n'est [accent]pas recommandé[] de se lancer dans de tels secteurs sans la technologie et la préparation appropriées. -hint.coreIncinerate = Lorsqu'un Noyau est rempli d'une ressource en particulier, le surplus qui rentrera dans celui-ci sera [accent]incinéré[]. +hint.coreIncinerate = Lorsqu'un Noyau est rempli d'une ressource en particulier, le surplus qui y rentrera sera [accent]incinéré[]. hint.factoryControl = Pour régler la [accent]destination[] d'une usine à unités, cliquez sur l'usine en mode « Commande », puis clic-droit sur la destination souhaitée.\nLes unités produites s'y déplaceront automatiquement. hint.factoryControl.mobile = Pour régler la [accent]destination[] d'une usine à unités, tapez sur l'usine en mode « Commande », puis tapez sur la destination souhaitée.\nLes unités produites s'y déplaceront automatiquement. @@ -1877,8 +1880,8 @@ gz.turrets = Recherchez et placez 2 \uf861 [accent]Duos[] pour défendre votre n gz.duoammo = Rechargez vos Duos avec du [accent]cuivre[], en utilisant les convoyeurs. gz.walls = Les [accent]Murs[] peuvent empêcher les attaques ennemies d'atteindre vos constructions.\nPlacez des \uf8ae [accent]murs de cuivre[] autour de vos tourelles. gz.defend = Ennemis en approche, préparez-vous à défendre. -gz.aa = Les unités aériennes ne peuvent pas être facilement repoussées avec des tourelles standard.\n\uf860 Les [accent]Disperseurs[] sont d'excellentes tourelles anti-aériennes, mais requierent du \uf837 [accent]plomb[] en tant que munition. -gz.scatterammo = Approvisionnez le Disperseur avec du [accent]plomb[], en utilisant des convoyeurs. +gz.aa = Les unités aériennes ne peuvent pas être facilement repoussées avec des tourelles standard.\n\uf860 Les [accent]Disperseurs[] sont d'excellentes tourelles anti-aériennes, mais requièrent du \uf837 [accent]plomb[] en tant que munition. +gz.scatterammo = Approvisionnez le Disperseur avec du [accent]plomb[] en utilisant des convoyeurs. gz.supplyturret = [accent]Approvisionnez la tourelle gz.zone1 = Ceci est la zone d'apparition ennemie. gz.zone2 = Tout ce qui est construit dans le rayon est détruit lors du commencement de la vague. @@ -1895,22 +1898,20 @@ onset.ducts.mobile = Recherchez et placez des \uf799 [accent]conduits[] pour dé onset.moremine = Étendez vos exploitations minières.\nPlacez plus de foreuses à plasma et utilisez des transmetteurs à rayons pour les relier.\nMinez 200 minerais de béryllium. onset.graphite = Les blocs plus complexes requièrent du \uf835 [accent]graphite[].\nPlacez quelques foreuses à plasma pour miner du graphite. onset.research2 = Commencez à rechercher des [accent]usines[].\nRecherchez le \uf74d [accent]broyeur de parois[] et le \uf779 [accent]four de silicium[]. -onset.arcfurnace = le four de silicium a besoin de \uf834 [accent]sable[] et de \uf835 [accent]graphite[] pour créer du \uf82f [accent]silicium[].\nDe [accent]l'énergie[] est aussi requise. +onset.arcfurnace = Le four de silicium a besoin de \uf834 [accent]sable[] et de \uf835 [accent]graphite[] pour créer du \uf82f [accent]silicium[].\nDe [accent]l'énergie[] est aussi requise. onset.crusher = Utilisez des \uf74d [accent]broyeurs de parois[] pour miner du sable. -onset.fabricator = Utilisez des [accent]unités[] pour explorer la carte, défendre vos constructions et attaquer l'ennemi. Recherchez et placez un \uf6a2 [accent]fabricateur de tanks[]. +onset.fabricator = Utilisez des [accent]Unités[] pour explorer la carte, défendre vos constructions et attaquer l'ennemi. Recherchez et placez un \uf6a2 [accent]Fabricateur de Tanks[]. onset.makeunit = Produisez une unité.\nUtilisez le bouton "?" pour voir les ressources requises par le fabricateur. onset.turrets = Les unités sont efficaces, mais les [accent]tourelles[] ont de meilleures capacités défensives si elles sont bien utilisées.\nPlacez une tourelle \uf6eb [accent]brèche[].\nLes tourelles requièrent des [accent]munitions[] \uf748. -onset.turretammo = Approvisionnez les tourelles avec du [accent]béryllium.[] +onset.turretammo = Approvisionnez les tourelles avec du [accent]béryllium[]. onset.walls = Les [accent]murs[] peuvent encaisser les dégâts des attaques ennemies avant qu'elles atteignent vos constructions.\nPlacez quelques \uf6ee [accent]murs de béryllium[] autour de la tourelle. onset.enemies = Ennemis en approche, préparez-vous à défendre. -onset.attack = L'ennemi est vulnérable. Contre-attaquez. +onset.attack = L'ennemi est vulnérable. Contre-attaquez ! onset.cores = Les noyaux peuvent être placés sur des [accent]tuiles de noyau[].\nCes nouveaux noyaux servent à faire avancer votre base et partager vos ressources avec d'autres noyaux.\nPlacez un noyau \uf725. onset.detect = L'ennemi sera capable de vous détecter dans 2 minutes.\nAméliorez vos défenses, vos exploitations minières ainsi que votre production. - -#Ne pas traduire -onset.commandmode = Hold [accent]shift[] to enter [accent]command mode[].\n[accent]Left-click and drag[] to select units.\n[accent]Right-click[] to order selected units to move or attack. -onset.commandmode.mobile = Press the [accent]command button[] to enter [accent]command mode[].\nHold down a finger, then [accent]drag[] to select units.\n[accent]Tap[] to order selected units to move or attack. -aegis.tungsten = Tungsten can be mined using an [accent]impact drill[].\nThis structure requires [accent]water[] and [accent]power[]. +onset.commandmode = Retenez [accent]Maj-gauche[] pour entrer en [accent]Mode « Commande »[].\n[accent]Clic-gauche tout en bougeant la souris[] pour sélectionner des unités.\n[accent]Clic-droit[] pour ordonner aux unités sélectionnées de bouger ou attaquer. +onset.commandmode.mobile = Pressez le [accent]bouton de commande[] pour entrer en [accent]Mode « Commande »[].\nRetenez votre doigt, et [accent]bougez-le[] pour sélectionner des unités.\n[accent]Tapez[] pour ordonner aux unités sélectionnées de bouger ou attaquer. +aegis.tungsten = Le tungstène peut être miné en utilisant une [accent]foreuse à impact[].\nCette structure requiert de [accent]l'eau[] et de [accent]l'énergie[]. split.pickup = Certains blocs peuvent être transportés par des unités du noyau.\nTransportez ce [accent]conteneur[] et placez-le sur le [accent]chargeur de charges utiles[].\n(Les touches par défaut sont [[ pour ramasser et ] pour déposer) split.pickup.mobile = Certains blocs peuvent être transportés par des unités du noyau.\nTransportez ce [accent]conteneur[] et placez-le sur le [accent]chargeur de charges utiles[].\n(Pour ramasser ou déposer quelque chose, Pressez longuement dessus.) @@ -1926,7 +1927,7 @@ item.metaglass.description = Un composé de verre super-résistant. Utilisation item.graphite.description = Du carbone minéralisé utilisé pour les munitions et dans les composants électriques. item.sand.description = Un matériau commun, largement utilisé pour la fabrication de matériaux raffinés. item.coal.description = Un carburant commun et facile à obtenir. -item.coal.details = De la matière végétale fossilisée, formée bien avant l’ensemencement de ce monde. Utilisation très répandue pour la production de carburant et de ressources. +item.coal.details = De la matière végétale fossilisée, formée bien avant l’ensemencement de ce monde. Utilisation très répandue pour la production de carburant et de ressources. item.titanium.description = Un métal rare et super-léger, largement utilisé dans le transport de liquides, dans les foreuses de haut niveau et dans les usines. item.thorium.description = Un métal dense et radioactif, utilisé comme support structurel et comme carburant nucléaire. item.scrap.description = Il est utilisé dans les fours à fusion et les pulvériseurs, pour être raffiné en d'autres matériaux. @@ -2113,7 +2114,7 @@ block.repair-turret.description = Répare en continu l'unité endommagée la plu block.payload-propulsion-tower.description = Structure de transport de charges utiles à longue portée. Projette des charges utiles vers d'autres tours de propulsion de charges utiles reliées. #Erekir -block.core-bastion.description = Le cœur de votre base. Blindé. Une fois détruit, le secteur est perdu. +block.core-bastion.description = Le cœur de votre base. Blindé. Une fois détruit, le secteur est perdu. block.core-citadel.description = Le cœur de votre base. Très bien blindé. Stocke plus de ressources qu'un noyau Bastion. block.core-acropolis.description = Le cœur de votre base. Exceptionnellement bien blindé. Stocke plus de ressources qu'un noyau Citadelle. block.breach.description = Tire des munitions perforantes de béryllium ou de tungstène sur les cibles ennemies. @@ -2297,19 +2298,19 @@ lst.setrate = Définit la vitesse d'exécution d'un processeur en instructions/t lst.fetch = Cherche les unités, noyaux, joueurs ou constructions par index. Commence à 0 et termine par le nombre retourné. lst.packcolor = Compresse les composants RGBA [0, 1] en un seul nombre pour les opérations de dessins ou les changements de règles. lst.setrule = Change une règle du jeu. -lst.flushmessage = Affiche un message sur l'écran depuis la mémoire tampon de texte.\nLe message apparait après la fin du dernier. +lst.flushmessage = Affiche un message sur l'écran depuis la mémoire tampon de texte.\nAttendra la fin du message précédent avant l'affichage du nouveau. lst.cutscene = Manipule la caméra du joueur. -lst.setflag = Définit un drapeau global qui peut être lu par tous les processeurs. -lst.getflag = Vérifie si un drapeau global est présent. +lst.setflag = Définit une variable globale qui peut être lue par tous les processeurs. +lst.getflag = Vérifie si une variable globale est présente. lst.setprop = Change une propriété d'une unité ou d'un bâtiment. -lst.effect = Create a particle effect. -lst.sync = Sync a variable across the network.\nOnly invoked 10 times a second at most. -lst.makemarker = Create a new logic marker in the world.\nAn ID to identify this marker must be provided.\nMarkers currently limited to 20,000 per world. -lst.setmarker = Set a property for a marker.\nThe ID used must be the same as in the Make Marker instruction. +lst.effect = Crée un effet de particules. +lst.sync = Synchronise une variable dans le réseau.\nLimité à 20 fois par seconde et par variable. +lst.makemarker = Crée un marqueur dans le monde.\nUn ID pour identifier le marqueur doit être donné.\nLes marqueurs sont limités à 20,000 par monde. +lst.setmarker = Change une propriété d'un marqueur.\nL'ID utilisé doit être le même que celui de l'instruction "Make Marker". logic.nounitbuild = [red]Les unités contrôlées par des processeurs ne peuvent pas construire ici. -lenum.type = Type de bâtiment/unité.\nPar exemple, pour tout routeur, cela retournera [accent]@router[].\nPas en texte. +lenum.type = Type de bâtiment/unité.\nPar exemple, pour tout routeur, cela retournera [accent]@router[]. lenum.shoot = Tire à une position donnée. lenum.shootp = Tire à une unité/bâtiment avec la prédiction de mouvement. lenum.config = La configuration d'un bâtiment. Par exemple, l'objet sélectionné dans un trieur. @@ -2321,7 +2322,7 @@ laccess.dead = Retourne si l'Unité/Bâtiment est morte/détruit ou plus valide. laccess.controlled = Retourne:\n[accent]@ctrlProcessor[] si le contrôleur de l'Unité est un processeur\n[accent]@ctrlPlayer[] si l'Unité/Bâtiment est contrôlé par un joueur\n[accent]@ctrlFormation[] si l'Unité est en formation\nSinon, retourne 0. laccess.progress = Progression de l'action, 0 à 1.\nRenvoie la progression de la production, du rechargement de la tourelle ou de la construction. laccess.speed = La vitesse maximale d'une unité, en blocs/sec. -laccess.id = ID of a unit/block/item/liquid.\nThis is the inverse of the lookup operation. +laccess.id = L'ID d'une unité/bloc/ressource/liquide.\nCeci est l'inverse de l'instruction de recherche. lcategory.unknown = Inconnu lcategory.unknown.description = Instructions sans catégorie. @@ -2332,7 +2333,7 @@ lcategory.block.description = Interagit avec les blocs. lcategory.operation = Opérations lcategory.operation.description = Opérations logiques. lcategory.control = Contrôle des Flux -lcategory.control.description = Manipule le flot d'exécution. +lcategory.control.description = Manipule l'ordre d'exécution. lcategory.unit = Contrôle des Unités lcategory.unit.description = Ordonne des commandes aux unités. lcategory.world = Contrôle du Monde @@ -2443,7 +2444,7 @@ lenum.unbind = Désactive complètement le contrôle par processeur.\nL'unité r lenum.move = Bouge vers la position exacte. lenum.approach = Approche une position avec un rayon. lenum.pathfind = Détermine un itinéraire et bouge vers le point d'apparition ennemi. -lenum.autopathfind = Automatically pathfinds to the nearest enemy core or drop point.\nThis is the same as standard wave enemy pathfinding. +lenum.autopathfind = Recherche automatiquement le chemin vers le noyau ennemi ou la zone d'apparition ennemie le plus proche.\nCeci est le même que la détection de chemin de la vague ennemie. lenum.target = Tire vers la position donnée. lenum.targetp = Tire sur une cible avec la prédiction de mouvement. lenum.itemdrop = Lâche un objet. diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties index 0b9e351e77..3aa426f974 100644 --- a/core/assets/bundles/bundle_hu.properties +++ b/core/assets/bundles/bundle_hu.properties @@ -1642,7 +1642,7 @@ block.duct-bridge.name = Szállítószalag Híd block.large-payload-mass-driver.name = Nagy Rakomány Tömegmozgató block.payload-void.name = Rakomány Megsemmisítő block.payload-source.name = Rakomány Készítő -block.disassembler.name = Szétszerelő +block.disassembler.name = Szétválasztó block.silicon-crucible.name = Szilícium Olvasztó block.overdrive-dome.name = Túlhajtó Búra block.interplanetary-accelerator.name = Bolygóközi Gyorsító @@ -1950,7 +1950,7 @@ item.carbide.description = Korszerű szerkezetekben, nehezebb egységekben és l liquid.water.description = Gépek hűtésére és Törmelékfeldolgozásra használható. liquid.slag.description = Leválasztóban finomítva értékes fémek forrása, az ellenségre fröcskölve gyilkos fegyver. liquid.oil.description = Magas szintű nyersanyagok gyártására vagy gyújtólövedékként használható. -liquid.cryofluid.description = Hűtőfolyadék a reaktorok, lövegtornyok és gyárak számára. +liquid.cryofluid.description = Hűtőfolyadék az erőművek, reaktorok, lövegtornyok és gyárak számára. #Erekir liquid.arkycite.description = Kémiai reakciókban használják energiatermelésre és anyagszintézisre. diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 10940b8be9..4485a18f9a 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1115,7 +1115,7 @@ setting.position.name = Отображать координаты игрока setting.mouseposition.name = Показывать позицию курсора setting.musicvol.name = Громкость музыки setting.atmosphere.name = Отображать атмосферу планеты -setting.drawlight.name = Draw Darkness/Lighting +setting.drawlight.name = Отображать тени/освещение setting.ambientvol.name = Громкость окружения setting.mutemusic.name = Заглушить музыку setting.sfxvol.name = Громкость эффектов diff --git a/core/src/mindustry/ai/types/CommandAI.java b/core/src/mindustry/ai/types/CommandAI.java index 2e2a24851d..80860d5f5d 100644 --- a/core/src/mindustry/ai/types/CommandAI.java +++ b/core/src/mindustry/ai/types/CommandAI.java @@ -399,6 +399,8 @@ public class CommandAI extends AIController{ @Override public void commandPosition(Vec2 pos){ + if(pos == null) return; + commandPosition(pos, false); if(commandController != null){ commandController.commandPosition(pos); @@ -406,8 +408,10 @@ public class CommandAI extends AIController{ } public void commandPosition(Vec2 pos, boolean stopWhenInRange){ - targetPos = pos; - lastTargetPos = pos; + if(pos == null) return; + + //this is an allocation, but it's relatively rarely called anyway, and outside mutations must be prevented + targetPos = lastTargetPos = pos.cpy(); attackTarget = null; pathId = Vars.controlPath.nextTargetId(); this.stopWhenInRange = stopWhenInRange; diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 775af9c679..1275b3b169 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -570,7 +570,7 @@ public class Blocks{ snowWall = new StaticWall("snow-wall"); duneWall = new StaticWall("dune-wall"){{ - basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this; + hotrock.asFloor().wall = magmarock.asFloor().wall = basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this; attributes.set(Attribute.sand, 2f); }}; @@ -2408,7 +2408,7 @@ public class Blocks{ largeSolarPanel = new SolarGenerator("solar-panel-large"){{ requirements(Category.power, with(Items.lead, 80, Items.silicon, 110, Items.phaseFabric, 15)); size = 3; - powerProduction = 1.3f; + powerProduction = 1.6f; }}; thoriumReactor = new NuclearReactor("thorium-reactor"){{ @@ -3968,6 +3968,7 @@ public class Blocks{ hitColor = Pal.meltdownHit; status = StatusEffects.melting; drawSize = 420f; + timescaleDamage = true; incendChance = 0.4f; incendSpread = 5f; diff --git a/core/src/mindustry/content/ErekirTechTree.java b/core/src/mindustry/content/ErekirTechTree.java index 89f128ae72..6c4571a43a 100644 --- a/core/src/mindustry/content/ErekirTechTree.java +++ b/core/src/mindustry/content/ErekirTechTree.java @@ -447,11 +447,11 @@ public class ErekirTechTree{ //nodeProduce(Liquids.gallium, () -> {}); }); + }); - nodeProduce(Items.surgeAlloy, () -> { - nodeProduce(Items.phaseFabric, () -> { + nodeProduce(Items.surgeAlloy, () -> { + nodeProduce(Items.phaseFabric, () -> { - }); }); }); }); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index f35ae0d9f9..bcb04b2fda 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -197,7 +197,7 @@ public class UnitTypes{ singleTarget = true; drownTimeMultiplier = 4f; - abilities.add(new ShieldRegenFieldAbility(25f, 500f, 60f * 1, 60f)); + abilities.add(new ShieldRegenFieldAbility(25f, 250f, 60f * 1, 60f)); BulletType smallBullet = new BasicBulletType(3f, 10){{ width = 7f; diff --git a/core/src/mindustry/entities/EntityGroup.java b/core/src/mindustry/entities/EntityGroup.java index 45e0377b97..ea8ef0cdb8 100644 --- a/core/src/mindustry/entities/EntityGroup.java +++ b/core/src/mindustry/entities/EntityGroup.java @@ -28,6 +28,7 @@ public class EntityGroup implements Iterable{ private int index; public static int nextId(){ + if(lastId >= Integer.MAX_VALUE - 2) lastId = 0; return lastId++; } diff --git a/core/src/mindustry/entities/abilities/ShieldArcAbility.java b/core/src/mindustry/entities/abilities/ShieldArcAbility.java index 632d0a58a7..b63a88bf1e 100644 --- a/core/src/mindustry/entities/abilities/ShieldArcAbility.java +++ b/core/src/mindustry/entities/abilities/ShieldArcAbility.java @@ -93,7 +93,8 @@ public class ShieldArcAbility extends Ability{ paramField = this; paramPos.set(x, y).rotate(unit.rotation - 90f).add(unit); - Groups.bullet.intersect(unit.x - radius, unit.y - radius, radius * 2f, radius * 2f, shieldConsumer); + float reach = radius + width / 2f; + Groups.bullet.intersect(paramPos.x - reach, paramPos.y - reach, reach * 2f, reach * 2f, shieldConsumer); }else{ widthScale = Mathf.lerpDelta(widthScale, 0f, 0.11f); } diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index b4c632ab98..4ab4c929a4 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -160,6 +160,8 @@ public class BulletType extends Content implements Cloneable{ /** Bullet type that is created when this bullet expires. */ public @Nullable BulletType fragBullet = null; + /** If true, frag bullets are delayed to the next frame. Fixes obscure bugs with piercing bullet types spawning frags immediately and screwing up the Damage temporary variables. */ + public boolean delayFrags = false; /** Degree spread range of fragmentation bullets. */ public float fragRandomSpread = 360f; /** Uniform spread between each frag bullet in degrees. */ @@ -446,7 +448,11 @@ public class BulletType extends Content implements Cloneable{ Effect.shake(hitShake, hitShake, b); if(fragOnHit){ - createFrags(b, x, y); + if(delayFrags && fragBullet != null && fragBullet.delayFrags){ + Core.app.post(() -> createFrags(b, x, y)); + }else{ + createFrags(b, x, y); + } } createPuddles(b, x, y); createIncend(b, x, y); diff --git a/core/src/mindustry/entities/bullet/ContinuousBulletType.java b/core/src/mindustry/entities/bullet/ContinuousBulletType.java index 0f95881285..a9ea18876b 100644 --- a/core/src/mindustry/entities/bullet/ContinuousBulletType.java +++ b/core/src/mindustry/entities/bullet/ContinuousBulletType.java @@ -11,6 +11,8 @@ public class ContinuousBulletType extends BulletType{ public float damageInterval = 5f; public boolean largeHit = false; public boolean continuous = true; + /** If a building fired this, whether to multiply damage by its timescale. */ + public boolean timescaleDamage = false; { removeAfterPierce = false; @@ -79,7 +81,12 @@ public class ContinuousBulletType extends BulletType{ } public void applyDamage(Bullet b){ + float damage = b.damage; + if(timescaleDamage && b.owner instanceof Building build){ + b.damage *= build.timeScale(); + } Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), currentLength(b), largeHit, laserAbsorb, pierceCap); + b.damage = damage; } public float currentLength(Bullet b){ diff --git a/core/src/mindustry/entities/bullet/LaserBulletType.java b/core/src/mindustry/entities/bullet/LaserBulletType.java index 7450824c4a..c6c7c3de21 100644 --- a/core/src/mindustry/entities/bullet/LaserBulletType.java +++ b/core/src/mindustry/entities/bullet/LaserBulletType.java @@ -38,6 +38,7 @@ public class LaserBulletType extends BulletType{ hittable = false; absorbable = false; removeAfterPierce = false; + delayFrags = true; } public LaserBulletType(){ diff --git a/core/src/mindustry/entities/bullet/RailBulletType.java b/core/src/mindustry/entities/bullet/RailBulletType.java index fb5c1814a1..276a428e4e 100644 --- a/core/src/mindustry/entities/bullet/RailBulletType.java +++ b/core/src/mindustry/entities/bullet/RailBulletType.java @@ -24,6 +24,7 @@ public class RailBulletType extends BulletType{ collides = false; keepVelocity = false; lifetime = 1f; + delayFrags = true; } @Override @@ -60,7 +61,7 @@ public class RailBulletType extends BulletType{ super.init(b); b.fdata = length; - Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), length, false, false); + Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), length, false, false, pierceCap); float resultLen = b.fdata; Vec2 nor = Tmp.v1.trns(b.rotation(), 1f).nor(); diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index dedcf105a2..73be92ad0d 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -1569,7 +1569,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ consumed = true; if((!config.isShown() && build.shouldShowConfigure(player)) //if the config fragment is hidden, show //alternatively, the current selected block can 'agree' to switch config tiles - || (config.isShown() && config.getSelected().onConfigureBuildTapped(build))){ + || (config.isShown() && config.getSelected().onConfigureBuildTapped(build) && build.shouldShowConfigure(player))){ Sounds.click.at(build); config.showConfig(build); } diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index bd06b9eefd..fea21b936b 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -1459,7 +1459,8 @@ public class LExecutor{ case ban -> { Object cont = exec.obj(value); if(cont instanceof Block b){ - state.rules.bannedBlocks.add(b); + // Rebuild PlacementFragment if anything has changed + if(state.rules.bannedBlocks.add(b) && !headless) ui.hudfrag.blockfrag.rebuild(); }else if(cont instanceof UnitType u){ state.rules.bannedUnits.add(u); } @@ -1467,7 +1468,7 @@ public class LExecutor{ case unban -> { Object cont = exec.obj(value); if(cont instanceof Block b){ - state.rules.bannedBlocks.remove(b); + if(state.rules.bannedBlocks.remove(b) && !headless) ui.hudfrag.blockfrag.rebuild(); }else if(cont instanceof UnitType u){ state.rules.bannedUnits.remove(u); } diff --git a/core/src/mindustry/maps/generators/BasicGenerator.java b/core/src/mindustry/maps/generators/BasicGenerator.java index e77cdde3e0..0305b1d3b0 100644 --- a/core/src/mindustry/maps/generators/BasicGenerator.java +++ b/core/src/mindustry/maps/generators/BasicGenerator.java @@ -335,7 +335,7 @@ public abstract class BasicGenerator implements WorldGenerator{ ore = tile.overlay(); r.get(tile.x, tile.y); tile.setFloor(floor.asFloor()); - tile.setBlock(block); + if(block != tile.block()) tile.setBlock(block); tile.setOverlay(ore); } } diff --git a/core/src/mindustry/service/GameService.java b/core/src/mindustry/service/GameService.java index 79d9aec342..7b31d10711 100644 --- a/core/src/mindustry/service/GameService.java +++ b/core/src/mindustry/service/GameService.java @@ -10,7 +10,6 @@ import mindustry.game.SectorInfo.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; -import mindustry.world.blocks.defense.*; import mindustry.world.blocks.defense.Wall.*; import mindustry.world.blocks.defense.turrets.Turret.*; import mindustry.world.blocks.distribution.*; @@ -111,16 +110,10 @@ public class GameService{ completeSerpulo.complete(); } - if(mods.list().size > 0){ + if(mods != null && mods.list().size > 0){ installMod.complete(); } - Events.on(ClientLoadEvent.class, e -> { - if(mods.list().size > 0){ - installMod.complete(); - } - }); - if(Core.bundle.get("yes").equals("router")){ routerLanguage.complete(); } @@ -231,8 +224,8 @@ public class GameService{ } } - if(e.tile.block() instanceof MendProjector || e.tile.block() instanceof RegenProjector) buildMendProjector.complete(); - if(e.tile.block() instanceof OverdriveProjector) buildOverdriveProjector.complete(); + if(e.tile.block() == Blocks.mendProjector) buildMendProjector.complete(); + if(e.tile.block() == Blocks.overdriveProjector) buildOverdriveProjector.complete(); if(e.tile.block() == Blocks.waterExtractor){ if(e.tile.getLinkedTiles(tmpTiles).contains(t -> t.floor().liquidDrop == Liquids.water)){ @@ -459,7 +452,8 @@ public class GameService{ //check unlocked stuff on load as well Events.on(ResearchEvent.class, e -> checkUnlocks.run()); Events.on(UnlockEvent.class, e -> checkUnlocks.run()); - Events.on(ClientLoadEvent.class, e -> checkUnlocks.run()); + + checkUnlocks.run(); Events.on(WinEvent.class, e -> { if(state.rules.pvp){ diff --git a/core/src/mindustry/ui/dialogs/JoinDialog.java b/core/src/mindustry/ui/dialogs/JoinDialog.java index b6b2476761..3092db179f 100644 --- a/core/src/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/mindustry/ui/dialogs/JoinDialog.java @@ -247,29 +247,12 @@ public class JoinDialog extends BaseDialog{ void setupServer(Server server, Host host){ server.lastHost = host; server.content.clear(); - buildServer(host, server.content); + buildServer(host, server.content, false); } - void buildServer(Host host, Table content){ + void buildServer(Host host, Table content, boolean inner){ content.top().left(); - String versionString; - - if(host.version == -1){ - versionString = Core.bundle.format("server.version", Core.bundle.get("server.custombuild"), ""); - }else if(host.version == 0){ - versionString = Core.bundle.get("server.outdated"); - }else if(host.version < Version.build && Version.build != -1){ - versionString = Core.bundle.get("server.outdated") + "\n" + - Core.bundle.format("server.version", host.version, ""); - }else if(host.version > Version.build && Version.build != -1){ - versionString = Core.bundle.get("server.outdated.client") + "\n" + - Core.bundle.format("server.version", host.version, ""); - }else if(host.version == Version.build && Version.type.equals(host.versionType)){ - //not important - versionString = ""; - }else{ - versionString = Core.bundle.format("server.version", host.version, host.versionType); - } + String versionString = getVersionString(host); float twidth = targetWidth() - 40f; @@ -277,12 +260,14 @@ public class JoinDialog extends BaseDialog{ Color color = Pal.gray; - content.table(Tex.whiteui, t -> { - t.left(); - t.setColor(color); + if(inner){ + content.table(Tex.whiteui, t -> { + t.left(); + t.setColor(color); - t.add(host.name + " " + versionString).style(Styles.outlineLabel).padLeft(10f).width(twidth).left().ellipsis(true); - }).growX().height(36f).row(); + t.add(host.name + " " + versionString).style(Styles.outlineLabel).padLeft(10f).width(twidth).left().ellipsis(true); + }).growX().height(36f).row(); + } content.table(Tex.whitePane, t -> { t.top().left(); @@ -485,11 +470,16 @@ public class JoinDialog extends BaseDialog{ void addCommunityHost(Host host, Table container){ global.background(null); + String versionString = getVersionString(host); float w = targetWidth(); container.left().top(); - container.button(b -> buildServer(host, b), style, () -> { + Button[] button = {null}; + + button[0] = container.button(b -> {}, style, () -> { + if(button[0].childrenPressed()) return; + Events.fire(new ClientPreConnectEvent(host)); if(!Core.settings.getBool("server-disclaimer", false)){ ui.showCustomConfirm("@warning", "@servers.disclaimer", "@ok", "@back", () -> { @@ -501,7 +491,28 @@ public class JoinDialog extends BaseDialog{ }else{ safeConnect(host.address, host.port, host.version); } - }).width(w).padBottom(7).padRight(4f).top().left().growY().uniformY(); + }).width(w).padBottom(7).padRight(4f).top().left().growY().uniformY().get(); + + Table inner = new Table(Tex.whiteui); + inner.setColor(Pal.gray); + + button[0].clearChildren(); + button[0].add(inner).growX(); + + inner.add(host.name + " " + versionString).left().padLeft(10f).wrap().style(Styles.outlineLabel).growX(); + + inner.button(Icon.add, Styles.emptyi, () -> { + Server server = new Server(); + server.setIP(host.address + ":" + host.port); + servers.add(server); + saveServers(); + setupRemote(); + refreshRemote(); + }).margin(3f).pad(8f).padRight(4f).top().right(); + + button[0].row(); + + buildServer(host, button[0].table(t -> {}).grow().get(), false); if((container.getChildren().size) % columns() == 0){ container.row(); @@ -532,7 +543,7 @@ public class JoinDialog extends BaseDialog{ local.row(); } - local.button(b -> buildServer(host, b), style, () -> { + local.button(b -> buildServer(host, b, true), style, () -> { Events.fire(new ClientPreConnectEvent(host)); safeConnect(host.address, host.port, host.version); }).width(w).top().left().growY(); @@ -641,6 +652,25 @@ public class JoinDialog extends BaseDialog{ Core.settings.putJson("servers", Server.class, servers); } + private String getVersionString(Host host){ + if(host.version == -1){ + return Core.bundle.format("server.version", Core.bundle.get("server.custombuild"), ""); + }else if(host.version == 0){ + return Core.bundle.get("server.outdated"); + }else if(host.version < Version.build && Version.build != -1){ + return Core.bundle.get("server.outdated") + "\n" + + Core.bundle.format("server.version", host.version, ""); + }else if(host.version > Version.build && Version.build != -1){ + return Core.bundle.get("server.outdated.client") + "\n" + + Core.bundle.format("server.version", host.version, ""); + }else if(host.version == Version.build && Version.type.equals(host.versionType)){ + //not important + return ""; + }else{ + return Core.bundle.format("server.version", host.version, host.versionType); + } + } + public static class Server{ public String ip; public int port; diff --git a/core/src/mindustry/ui/fragments/PlacementFragment.java b/core/src/mindustry/ui/fragments/PlacementFragment.java index ecdb326366..2c3e6ad524 100644 --- a/core/src/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/mindustry/ui/fragments/PlacementFragment.java @@ -113,7 +113,7 @@ public class PlacementFragment{ return hover; } - void rebuild(){ + public void rebuild(){ //category does not change on rebuild anymore, only on new world load Group group = toggler.parent; int index = toggler.getZIndex(); diff --git a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java index 2cbf82e0e9..6d3683958f 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java @@ -78,7 +78,7 @@ public class LaserTurret extends PowerTurret{ entry.bullet.set(bulletX, bulletY); entry.bullet.time = entry.bullet.type.lifetime * entry.bullet.type.optimalLifeFract; entry.bullet.keepAlive = true; - entry.life -= Time.delta / Math.max(efficiency, 0.00001f); + entry.life -= Time.delta * timeScale / Math.max(efficiency, 0.00001f); } wasShooting = true; diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index beb3e79d02..8688ae7889 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -418,14 +418,23 @@ public class ItemBridge extends Block{ checkAccept(source, world.tile(link)); } - protected boolean checkAccept(Building source, Tile other){ + protected boolean checkAccept(Building source, Tile link){ if(tile == null || linked(source)) return true; - if(linkValid(tile, other)){ - int rel = relativeTo(other); + if(linkValid(tile, link)){ + int rel = relativeTo(link); var facing = Edges.getFacingEdge(source, this); int rel2 = facing == null ? -1 : relativeTo(facing); + //this is a bug, but it is kept for compatibility, see: https://github.com/Anuken/Mindustry/issues/9257#issuecomment-1801998747 + /* + for(int j = 0; j < incoming.size; j++){ + int v = incoming.items[j]; + if(relativeTo(Point2.x(v), Point2.y(v)) == rel2){ + return false; + } + }*/ + return rel != rel2; } diff --git a/core/src/mindustry/world/blocks/power/BeamNode.java b/core/src/mindustry/world/blocks/power/BeamNode.java index e9c9fad6db..b99590d2be 100644 --- a/core/src/mindustry/world/blocks/power/BeamNode.java +++ b/core/src/mindustry/world/blocks/power/BeamNode.java @@ -122,9 +122,10 @@ public class BeamNode extends PowerBlock{ @Override public BlockStatus status(){ - if(Mathf.equal(power.status, 0f, 0.001f)) return BlockStatus.noInput; - if(Mathf.equal(power.status, 1f, 0.001f)) return BlockStatus.active; - return BlockStatus.noOutput; + float balance = power.graph.getPowerBalance(); + if(balance > 0f) return BlockStatus.active; + if(balance < 0f && power.graph.getLastPowerStored() > 0) return BlockStatus.noOutput; + return BlockStatus.noInput; } @Override diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index d681389ca5..31d0666b14 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -5,6 +5,7 @@ import arc.struct.*; import arc.util.*; import mindustry.content.*; import mindustry.gen.*; +import mindustry.logic.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.storage.CoreBlock.*; @@ -100,6 +101,12 @@ public class StorageBlock extends Block{ } } + @Override + public double sense(LAccess sensor){ + if(sensor == LAccess.itemCapacity && linkedCore != null) return linkedCore.sense(sensor); + return super.sense(sensor); + } + @Override public void overwrote(Seq previous){ //only add prev items when core is not linked diff --git a/core/src/mindustry/world/blocks/units/UnitAssembler.java b/core/src/mindustry/world/blocks/units/UnitAssembler.java index 44165f636f..bff1cdf800 100644 --- a/core/src/mindustry/world/blocks/units/UnitAssembler.java +++ b/core/src/mindustry/world/blocks/units/UnitAssembler.java @@ -444,7 +444,7 @@ public class UnitAssembler extends PayloadBlock{ if(!net.client()){ var unit = plan.unit.create(team); - if(unit != null && unit.isCommandable()){ + if(unit != null && unit.isCommandable() && commandPos != null){ unit.command().commandPosition(commandPos); } unit.set(spawn.x + Mathf.range(0.001f), spawn.y + Mathf.range(0.001f)); diff --git a/servers_v7.json b/servers_v7.json index c482219b76..e7f13e6ca7 100644 --- a/servers_v7.json +++ b/servers_v7.json @@ -3,17 +3,21 @@ "name": "meiqiuMDT", "address": ["cn1.plush.run:10001","211.101.236.94:10000","bj-1.lcf.icu:10240","play.simpfun.cn:14523"] }, + { + "name": "Crux's Revelations", + "address": ["fsn1.bbn.one:52397","fsn1.bbn.one:58375","de-free-01.hosts.optikservers.com:32212","fsn1.bbn.one:49840","de-free-01.hosts.optikservers.com:30449"] + }, { "name": "CMS", "address": ["195.2.84.144"] }, { - "name": "ShardDustry Events", - "address": ["194.247.42.11:27703"] + "name": "ShardDustry Eventos", + "address": ["45.158.9.198:31290"] }, { - "name": "ShardDustry", - "address": ["94.130.132.149:35689", "78.46.39.20:5552","45.158.9.198:30529"] + "name": "ShardDustry ES", + "address": ["94.130.132.149:35689","94.130.132.149:35438","45.158.9.198:31290","45.158.9.198:30529"] }, { "name": "Tamazia", @@ -69,16 +73,12 @@ }, { "name": "KMWStudios", - "address": ["46.151.26.232:1024", "46.151.26.232:2000", "46.151.26.232:3000", "46.151.26.232:4000", "46.151.26.232:6000", "46.151.26.232:7000", "46.151.26.232:8000"] + "address": ["x.kmwstudios.xyz:9000", "x.kmwstudios.xyz:9002", "x.kmwstudios.xyz:9003", "x.kmwstudios.xyz:9004", "x.kmwstudios.xyz:9005", "x.kmwstudios.xyz:9006", "x.kmwstudios.xyz:9007"] }, { "name": "XCore", "address": ["130.61.52.25", "130.61.52.25:6568", "130.61.52.25:6569", "130.61.52.25:6570", "130.61.52.25:6571", "130.61.52.25:6572", "130.61.52.25:6573", "130.61.52.25:6888"] }, - { - "name": "Darkdustry", - "address": ["130.61.78.82:3000", "130.61.78.82:3001", "130.61.78.82:3002", "130.61.78.82:3003", "130.61.78.82:3004", "130.61.78.82:3005", "130.61.78.82:3006", "130.61.78.82:3007", "130.61.78.82:3008", "130.61.78.82:3009", "130.61.78.82:3010"] - }, { "name": "Chaotic Neutral", "address": ["c-n.ddns.net:7012", "c-n.ddns.net:7013", "c-n.ddns.net:7014", "c-n.ddns.net:7015", "c-n.ddns.net:7016", "c-n.ddns.net:7017", "c-n.ddns.net:7003", "37.187.73.180:7021"] @@ -89,7 +89,7 @@ }, { "name": "Korea", - "address": ["mindustry.kr", "mindustry.kr:7105"] + "address": ["mindustry.kr"] }, { "name": "Phoenix Network", @@ -167,10 +167,6 @@ "name": "Router Pi", "address": ["a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6568", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6569", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6570", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6571", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6572", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6573", "a55c81b7c4d6e6d604651a93f8af5cd83.asuscomm.com:6574"] }, - { - "name": "Vndustry", - "address": ["185.128.227.11", "27.50.72.82:25334"] - }, { "name": "Anana&ShenYv", "address": ["mdtleague.top"] @@ -218,7 +214,7 @@ }, { "name": "MeowIsland", - "address": ["n1.mindustry.me:6590", "n1.mindustry.me:6592", "n1.mindustry.me:6595"] + "address": ["nexus.minecraft.rent:25598", "nexus.minecraft.rent:25596", "jupiter.minecraft.rent:25651"] }, { "name": "3MIDustry", @@ -226,7 +222,7 @@ }, { "name": "ABCXYZ Community", - "address": ["118.127.8.162:25617", "78.108.218.117:25640", "srv3.godlike.club:27246"] + "address": ["23.88.73.88:23591", "23.88.73.88:23539", "144.76.57.59:14996", "144.76.57.59:16881", "144.76.57.59:13885", "5.9.8.124:17775"] }, { "name": "CroCraft Network", @@ -246,7 +242,7 @@ }, { "name": "XuwenHost", - "address": ["pi.xiyuchao.love:6567","mdt.xuwenblock.cn:6567"] + "address": ["mdt.xuwenblock.cn:6568","mdt.xuwenblock.cn:6567","106.14.14.210"] }, { "name": "MineCore", diff --git a/tests/src/test/java/ModTestExotic.java b/tests/src/test/java/ModTestAllure.java similarity index 76% rename from tests/src/test/java/ModTestExotic.java rename to tests/src/test/java/ModTestAllure.java index 88aa06a196..56dad03283 100644 --- a/tests/src/test/java/ModTestExotic.java +++ b/tests/src/test/java/ModTestAllure.java @@ -13,17 +13,14 @@ import static org.junit.jupiter.api.Assertions.*; //- it is probably the mod with the most json, and as such covers a lot of classes //- it is popular enough in the mod browser //- I am somewhat familiar with its files & the type of content it adds -public class ModTestExotic extends GenericModTest{ +public class ModTestAllure extends GenericModTest{ @Test public void begin(){ - //TODO broken as of 136+ - if(true) return; + grabMod("https://github.com/BlueWolf3682/Allure/archive/4150f74db1ea6058dc090959cf0fe5dc9d239e37.zip"); + checkExistence("allure"); - grabMod("https://github.com/BlueWolf3682/Exotic-Mod/archive/08c861398ac9c3d1292132f9a110e17e06294a90.zip"); - checkExistence("exotic-mod"); - - UnitType type = Vars.content.units().find(u -> u.name.equals("exotic-mod-luminance")); + UnitType type = Vars.content.unit("allure-0b11-exodus"); assertNotNull(type, "A mod unit must be loaded."); assertTrue(type.weapons.size > 0, "A mod unit must have a weapon."); diff --git a/tests/src/test/java/ModTestBM.java b/tests/src/test/java/ModTestBM.java index 3ba96be88e..24e817b441 100644 --- a/tests/src/test/java/ModTestBM.java +++ b/tests/src/test/java/ModTestBM.java @@ -16,10 +16,7 @@ public class ModTestBM extends GenericModTest{ @Test public void begin(){ - //TODO broken as of 136+ - if(true) return; - - grabMod("https://github.com/sk7725/BetaMindy/releases/download/v0.955/BetaMindy.jar"); + grabMod("https://github.com/sk7725/BetaMindy/releases/download/v1.11/BetaMindy.jar"); checkExistence("betamindy");