| 
									
										
										
										
											2021-07-22 01:08:44 +02:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-08-05 13:17:01 -05:00
										 |  |  | import json | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  | import settings | 
					
						
							|  |  |  | import typing | 
					
						
							| 
									
										
										
										
											2021-08-05 13:17:01 -05:00
										 |  |  | from base64 import b64encode, b64decode | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  | from typing import Dict, Any | 
					
						
							| 
									
										
										
										
											2021-07-12 13:54:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  | from BaseClasses import Region, Entrance, Item, Tutorial, ItemClassification, Location | 
					
						
							|  |  |  | from worlds.AutoWorld import World, WebWorld | 
					
						
							| 
									
										
											  
											
												Minecraft Randomizer
Squash merge, original Commits:
* Minecraft locations, items, and generation without logic
* added id lookup for minecraft
* typing import fix in minecraft/Items.py
* fix 2
* implementing Minecraft options and hard/postgame advancement exclusion
* first logic pass (75/80)
* logic pass 2 and proper completion conditions
* added insane difficulty pool, modified method of excluding item pools for easier extension
* bump network_data_package version
* minecraft testing framework
* switch Ancient Debris to Netherite Scrap to avoid advancement triggering on receiving that item
* Testing now functions, split tests up by advancement pane, added some story tests
* Newer testing framework: every advancement gets its own function, for ease of testing
* fixed logic for The End... Again...
* changed option names to "include_hard_advancements" etc.
* village/pillager-related advancements now require can_adventure: weapon + food
* a few minecraft tests
* rename "Flint & Steel" to "Flint and Steel" for parity with in-game name
* additional MC tests
* more tests, mostly nether-related tests
* more tests, removed anvil path for Two Birds One Arrow
* include Minecraft slot data, and a world seed for each Minecraft player slot
* Added new items: ender pearls, lapis, porkchops
* All remaining Minecraft tests
* formatting of Minecraft tests and logic for better readability
* require Wither kill for Monsters Hunted
* properly removed 8 Emeralds item from item pool
* enchanting required for wither; fishing rod required for water breathing; water breathing required for elder guardian kill
* Added 12 new advancements (ported from old achievement system)
* renamed "On a Rail" for consistency with modern advancements
* tests for the new advancements
* moved slot_data generation for minecraft into worlds/minecraft/__init__.py, added logic_version to slot_data
* output minecraft options in the spoiler log
* modified advancement goal values for new advancements
* make non-native Minecraft items appear as Shovel in ALttP, and unknown-game items as Power Stars
* fixed glowstone block logic for Not Quite Nine Lives
* setup for shuffling MC structures: building ER world and shuffling regions/entrances
* ensured Nether Fortresses can't be placed in the End
* finished logic for structure randomization
* fixed nonnative items always showing up as Hammers in ALttP shops
* output minecraft structure info in the spoiler
* generate .apmc file for communication with MC client
* fixed structure rando always using the same seed
* move stuff to worlds/minecraft/Regions.py
* make output apmc file have consistent name with other files
* added minecraft bottle macro; fixed tests imports
* generalizing MC region generation
* restructured structure shuffling in preparation for structure plando
* only output structure rando info in spoiler if they are shuffled
* Force structure rando to always be off, for the stable release
* added Minecraft options to player settings
* formally added combat_difficulty as an option
* Added Ender Dragon into playthrough, cleaned up goal map
* Added new difficulties: Easy, Normal, Hard combat
* moved .apmc generation time to prevent outputs on failed generation
* updated tests for new combat logic
* Fixed bug causing generation to fail; removed Nether Fortress event since it should no longer be needed with the fix
* moved all MC-specific functions into gen_minecraft
* renamed "logic_version" to "client_version"
* bug fixes
properly flagged event locations/items with id None
moved generation back to Main.py to fix mysterious generation failures
* moved link_minecraft_regions into minecraft init, left create_regions in Main for caching
* added seed_name, player_name, client_version to apmc file
* reenabled structure shuffle
* added entrance tests for minecraft
Co-authored-by: achuang <alexander.w.chuang@gmail.com>
											
										 
											2021-05-08 07:38:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  | from . import Constants | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  | from .Options import MinecraftOptions | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  | from .Structures import shuffle_structures | 
					
						
							|  |  |  | from .ItemPool import build_item_pool, get_junk_item_names | 
					
						
							|  |  |  | from .Rules import set_rules | 
					
						
							| 
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-11 14:22:16 -07:00
										 |  |  | client_version = 9 | 
					
						
							| 
									
										
										
										
											2022-04-12 14:37:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class MinecraftSettings(settings.Group): | 
					
						
							|  |  |  |     class ForgeDirectory(settings.OptionalUserFolderPath): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class ReleaseChannel(str): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         release channel, currently "release", or "beta" | 
					
						
							|  |  |  |         any games played on the "beta" channel have a high likelihood of no longer working on the "release" channel. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 09:42:54 -04:00
										 |  |  |     class JavaExecutable(settings.OptionalUserFilePath): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Path to Java executable. If not set, will attempt to fall back to Java system installation. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     forge_directory: ForgeDirectory = ForgeDirectory("Minecraft NeoForge server") | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  |     max_heap_size: str = "2G" | 
					
						
							|  |  |  |     release_channel: ReleaseChannel = ReleaseChannel("release") | 
					
						
							| 
									
										
										
										
											2025-05-22 09:42:54 -04:00
										 |  |  |     java: JavaExecutable = JavaExecutable("") | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-12 14:37:05 -07:00
										 |  |  | class MinecraftWebWorld(WebWorld): | 
					
						
							|  |  |  |     theme = "jungle" | 
					
						
							|  |  |  |     bug_report_page = "https://github.com/KonoTyran/Minecraft_AP_Randomizer/issues/new?assignees=&labels=bug&template=bug_report.yaml&title=%5BBug%5D%3A+Brief+Description+of+bug+here" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 |  |  |     setup = Tutorial( | 
					
						
							| 
									
										
										
										
											2024-02-20 11:22:32 -05:00
										 |  |  |         "Multiworld Setup Guide", | 
					
						
							| 
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 |  |  |         "A guide to setting up the Archipelago Minecraft software on your computer. This guide covers" | 
					
						
							| 
									
										
										
										
											2022-05-19 12:15:23 -04:00
										 |  |  |         "single-player, multiworld, and related software.", | 
					
						
							| 
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 |  |  |         "English", | 
					
						
							|  |  |  |         "minecraft_en.md", | 
					
						
							|  |  |  |         "minecraft/en", | 
					
						
							|  |  |  |         ["Kono Tyran"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setup_es = Tutorial( | 
					
						
							|  |  |  |         setup.tutorial_name, | 
					
						
							|  |  |  |         setup.description, | 
					
						
							|  |  |  |         "Español", | 
					
						
							|  |  |  |         "minecraft_es.md", | 
					
						
							|  |  |  |         "minecraft/es", | 
					
						
							|  |  |  |         ["Edos"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setup_sv = Tutorial( | 
					
						
							|  |  |  |         setup.tutorial_name, | 
					
						
							|  |  |  |         setup.description, | 
					
						
							|  |  |  |         "Swedish", | 
					
						
							|  |  |  |         "minecraft_sv.md", | 
					
						
							|  |  |  |         "minecraft/sv", | 
					
						
							|  |  |  |         ["Albinum"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 23:17:54 +01:00
										 |  |  |     setup_fr = Tutorial( | 
					
						
							|  |  |  |         setup.tutorial_name, | 
					
						
							|  |  |  |         setup.description, | 
					
						
							|  |  |  |         "Français", | 
					
						
							|  |  |  |         "minecraft_fr.md", | 
					
						
							|  |  |  |         "minecraft/fr", | 
					
						
							|  |  |  |         ["TheLynk"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tutorials = [setup, setup_es, setup_sv, setup_fr] | 
					
						
							| 
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-12 14:37:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 |  |  | class MinecraftWorld(World): | 
					
						
							| 
									
										
										
										
											2021-08-31 17:28:46 -04:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     Minecraft is a game about creativity. In a world made entirely of cubes, you explore, discover, mine, | 
					
						
							|  |  |  |     craft, and try not to explode. Delve deep into the earth and discover abandoned mines, ancient | 
					
						
							|  |  |  |     structures, and materials to create a portal to another world. Defeat the Ender Dragon, and claim | 
					
						
							|  |  |  |     victory! | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  |     game = "Minecraft" | 
					
						
							|  |  |  |     options_dataclass = MinecraftOptions | 
					
						
							|  |  |  |     options: MinecraftOptions | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  |     settings: typing.ClassVar[MinecraftSettings] | 
					
						
							| 
									
										
										
										
											2021-07-08 11:07:41 +02:00
										 |  |  |     topology_present = True | 
					
						
							| 
									
										
										
										
											2022-04-12 14:37:05 -07:00
										 |  |  |     web = MinecraftWebWorld() | 
					
						
							| 
									
										
											  
											
												Minecraft Randomizer
Squash merge, original Commits:
* Minecraft locations, items, and generation without logic
* added id lookup for minecraft
* typing import fix in minecraft/Items.py
* fix 2
* implementing Minecraft options and hard/postgame advancement exclusion
* first logic pass (75/80)
* logic pass 2 and proper completion conditions
* added insane difficulty pool, modified method of excluding item pools for easier extension
* bump network_data_package version
* minecraft testing framework
* switch Ancient Debris to Netherite Scrap to avoid advancement triggering on receiving that item
* Testing now functions, split tests up by advancement pane, added some story tests
* Newer testing framework: every advancement gets its own function, for ease of testing
* fixed logic for The End... Again...
* changed option names to "include_hard_advancements" etc.
* village/pillager-related advancements now require can_adventure: weapon + food
* a few minecraft tests
* rename "Flint & Steel" to "Flint and Steel" for parity with in-game name
* additional MC tests
* more tests, mostly nether-related tests
* more tests, removed anvil path for Two Birds One Arrow
* include Minecraft slot data, and a world seed for each Minecraft player slot
* Added new items: ender pearls, lapis, porkchops
* All remaining Minecraft tests
* formatting of Minecraft tests and logic for better readability
* require Wither kill for Monsters Hunted
* properly removed 8 Emeralds item from item pool
* enchanting required for wither; fishing rod required for water breathing; water breathing required for elder guardian kill
* Added 12 new advancements (ported from old achievement system)
* renamed "On a Rail" for consistency with modern advancements
* tests for the new advancements
* moved slot_data generation for minecraft into worlds/minecraft/__init__.py, added logic_version to slot_data
* output minecraft options in the spoiler log
* modified advancement goal values for new advancements
* make non-native Minecraft items appear as Shovel in ALttP, and unknown-game items as Power Stars
* fixed glowstone block logic for Not Quite Nine Lives
* setup for shuffling MC structures: building ER world and shuffling regions/entrances
* ensured Nether Fortresses can't be placed in the End
* finished logic for structure randomization
* fixed nonnative items always showing up as Hammers in ALttP shops
* output minecraft structure info in the spoiler
* generate .apmc file for communication with MC client
* fixed structure rando always using the same seed
* move stuff to worlds/minecraft/Regions.py
* make output apmc file have consistent name with other files
* added minecraft bottle macro; fixed tests imports
* generalizing MC region generation
* restructured structure shuffling in preparation for structure plando
* only output structure rando info in spoiler if they are shuffled
* Force structure rando to always be off, for the stable release
* added Minecraft options to player settings
* formally added combat_difficulty as an option
* Added Ender Dragon into playthrough, cleaned up goal map
* Added new difficulties: Easy, Normal, Hard combat
* moved .apmc generation time to prevent outputs on failed generation
* updated tests for new combat logic
* Fixed bug causing generation to fail; removed Nether Fortress event since it should no longer be needed with the fix
* moved all MC-specific functions into gen_minecraft
* renamed "logic_version" to "client_version"
* bug fixes
properly flagged event locations/items with id None
moved generation back to Main.py to fix mysterious generation failures
* moved link_minecraft_regions into minecraft init, left create_regions in Main for caching
* added seed_name, player_name, client_version to apmc file
* reenabled structure shuffle
* added entrance tests for minecraft
Co-authored-by: achuang <alexander.w.chuang@gmail.com>
											
										 
											2021-05-08 07:38:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  |     item_name_to_id = Constants.item_name_to_id | 
					
						
							|  |  |  |     location_name_to_id = Constants.location_name_to_id | 
					
						
							| 
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  |     def _get_mc_data(self) -> Dict[str, Any]: | 
					
						
							|  |  |  |         exits = [connection[0] for connection in Constants.region_info["default_connections"]] | 
					
						
							| 
									
										
										
										
											2021-06-15 18:15:05 -05:00
										 |  |  |         return { | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  |             'world_seed': self.random.getrandbits(32), | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |             'seed_name': self.multiworld.seed_name, | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  |             'player_name': self.player_name, | 
					
						
							| 
									
										
										
										
											2021-06-15 18:15:05 -05:00
										 |  |  |             'player_id': self.player, | 
					
						
							|  |  |  |             'client_version': client_version, | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |             'structures': {exit: self.multiworld.get_entrance(exit, self.player).connected_region.name for exit in exits}, | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  |             'advancement_goal': self.options.advancement_goal.value, | 
					
						
							|  |  |  |             'egg_shards_required': min(self.options.egg_shards_required.value, | 
					
						
							|  |  |  |                                        self.options.egg_shards_available.value), | 
					
						
							|  |  |  |             'egg_shards_available': self.options.egg_shards_available.value, | 
					
						
							|  |  |  |             'required_bosses': self.options.required_bosses.current_key, | 
					
						
							|  |  |  |             'MC35': bool(self.options.send_defeated_mobs.value), | 
					
						
							|  |  |  |             'death_link': bool(self.options.death_link.value), | 
					
						
							|  |  |  |             'starting_items': json.dumps(self.options.starting_items.value), | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |             'race': self.multiworld.is_race, | 
					
						
							| 
									
										
										
										
											2021-06-15 18:15:05 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  |     def create_item(self, name: str) -> Item: | 
					
						
							|  |  |  |         item_class = ItemClassification.filler | 
					
						
							|  |  |  |         if name in Constants.item_info["progression_items"]: | 
					
						
							|  |  |  |             item_class = ItemClassification.progression | 
					
						
							|  |  |  |         elif name in Constants.item_info["useful_items"]: | 
					
						
							|  |  |  |             item_class = ItemClassification.useful | 
					
						
							|  |  |  |         elif name in Constants.item_info["trap_items"]: | 
					
						
							|  |  |  |             item_class = ItemClassification.trap | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return MinecraftItem(name, item_class, self.item_name_to_id.get(name, None), self.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_event(self, region_name: str, event_name: str) -> None: | 
					
						
							|  |  |  |         region = self.multiworld.get_region(region_name, self.player) | 
					
						
							|  |  |  |         loc = MinecraftLocation(self.player, event_name, None, region) | 
					
						
							|  |  |  |         loc.place_locked_item(self.create_event_item(event_name)) | 
					
						
							|  |  |  |         region.locations.append(loc) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  |     def create_event_item(self, name: str) -> Item: | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  |         item = self.create_item(name) | 
					
						
							|  |  |  |         item.classification = ItemClassification.progression | 
					
						
							|  |  |  |         return item | 
					
						
							| 
									
										
										
										
											2021-06-15 18:15:05 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  |     def create_regions(self) -> None: | 
					
						
							|  |  |  |         # Create regions | 
					
						
							|  |  |  |         for region_name, exits in Constants.region_info["regions"]: | 
					
						
							|  |  |  |             r = Region(region_name, self.player, self.multiworld) | 
					
						
							|  |  |  |             for exit_name in exits: | 
					
						
							|  |  |  |                 r.exits.append(Entrance(self.player, exit_name, r)) | 
					
						
							|  |  |  |             self.multiworld.regions.append(r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Bind mandatory connections | 
					
						
							|  |  |  |         for entr_name, region_name in Constants.region_info["mandatory_connections"]: | 
					
						
							|  |  |  |             e = self.multiworld.get_entrance(entr_name, self.player) | 
					
						
							|  |  |  |             r = self.multiworld.get_region(region_name, self.player) | 
					
						
							|  |  |  |             e.connect(r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add locations | 
					
						
							|  |  |  |         for region_name, locations in Constants.location_info["locations_by_region"].items(): | 
					
						
							|  |  |  |             region = self.multiworld.get_region(region_name, self.player) | 
					
						
							|  |  |  |             for loc_name in locations: | 
					
						
							|  |  |  |                 loc = MinecraftLocation(self.player, loc_name, | 
					
						
							|  |  |  |                     self.location_name_to_id.get(loc_name, None), region) | 
					
						
							|  |  |  |                 region.locations.append(loc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add events | 
					
						
							|  |  |  |         self.create_event("Nether Fortress", "Blaze Rods") | 
					
						
							|  |  |  |         self.create_event("The End", "Ender Dragon") | 
					
						
							|  |  |  |         self.create_event("Nether Fortress", "Wither") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Shuffle the connections | 
					
						
							|  |  |  |         shuffle_structures(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_items(self) -> None: | 
					
						
							|  |  |  |         self.multiworld.itempool += build_item_pool(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_rules = set_rules | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def generate_output(self, output_directory: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-06-15 18:15:05 -05:00
										 |  |  |         data = self._get_mc_data() | 
					
						
							| 
									
										
										
										
											2023-10-28 21:43:09 +02:00
										 |  |  |         filename = f"{self.multiworld.get_out_file_name_base(self.player)}.apmc" | 
					
						
							| 
									
										
										
										
											2021-07-22 01:08:44 +02:00
										 |  |  |         with open(os.path.join(output_directory, filename), 'wb') as f: | 
					
						
							| 
									
										
										
										
											2021-06-15 18:22:12 -05:00
										 |  |  |             f.write(b64encode(bytes(json.dumps(data), 'utf-8'))) | 
					
						
							| 
									
										
										
										
											2021-06-15 18:15:05 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  |     def fill_slot_data(self) -> dict: | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  |         return self._get_mc_data() | 
					
						
							| 
									
										
										
										
											2021-07-12 13:54:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  |     def get_filler_item_name(self) -> str: | 
					
						
							| 
									
										
										
										
											2024-08-19 15:58:30 -07:00
										 |  |  |         return get_junk_item_names(self.random, 1)[0] | 
					
						
							| 
									
										
										
										
											2023-03-08 21:13:52 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MinecraftLocation(Location): | 
					
						
							|  |  |  |     game = "Minecraft" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MinecraftItem(Item): | 
					
						
							|  |  |  |     game = "Minecraft" | 
					
						
							| 
									
										
										
										
											2022-06-17 03:23:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-05 13:17:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 17:28:46 -04:00
										 |  |  | def mc_update_output(raw_data, server, port): | 
					
						
							| 
									
										
										
										
											2021-08-05 13:17:01 -05:00
										 |  |  |     data = json.loads(b64decode(raw_data)) | 
					
						
							|  |  |  |     data['server'] = server | 
					
						
							|  |  |  |     data['port'] = port | 
					
						
							|  |  |  |     return b64encode(bytes(json.dumps(data), 'utf-8')) |