package electroblob.wizardry; import electroblob.wizardry.block.BlockBookshelf; import electroblob.wizardry.command.CommandCastSpell; import electroblob.wizardry.command.CommandDiscoverSpell; import electroblob.wizardry.command.CommandSetAlly; import electroblob.wizardry.command.CommandViewAllies; import electroblob.wizardry.data.DispenserCastingData; import electroblob.wizardry.data.WizardData; import electroblob.wizardry.integration.antiqueatlas.WizardryAntiqueAtlasIntegration; import electroblob.wizardry.integration.baubles.WizardryBaublesIntegration; import electroblob.wizardry.inventory.ContainerBookshelf; import electroblob.wizardry.misc.DonationPerksHandler; import electroblob.wizardry.misc.Forfeit; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryLoot; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellNetworkIDSorter; import electroblob.wizardry.util.SpellProperties; import electroblob.wizardry.util.WandHelper; import electroblob.wizardry.worldgen.WorldGenCrystalFlower; import electroblob.wizardry.worldgen.WorldGenCrystalOre; import electroblob.wizardry.worldgen.WorldGenLibraryRuins; import electroblob.wizardry.worldgen.WorldGenObelisk; import electroblob.wizardry.worldgen.WorldGenShrine; import electroblob.wizardry.worldgen.WorldGenUndergroundLibraryRuins; import electroblob.wizardry.worldgen.WorldGenWizardTower; import net.minecraft.item.Item; import net.minecraft.util.SoundCategory; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLServerStartingEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; import org.apache.logging.log4j.Logger; import java.io.File; import java.util.Calendar; /** * "Electroblob's Wizardry adds an RPG-like system of spells to Minecraft, with the aim of being as playable as * possible. No crazy constructs, no perk trees, no complex recipes - simply find spell books, cast spells, and master * the arcane! - But you knew that, right?" *

* Main mod class for Wizardry. Contains the logger and settings instances, along with all the other stuff that's normally * in a main mod class. * @author Electroblob * @since Wizardry 1.0 */ @Mod(modid = Wizardry.MODID, name = Wizardry.NAME, version = Wizardry.VERSION, acceptedMinecraftVersions = "[1.12.2]", guiFactory = "electroblob.wizardry.WizardryGuiFactory", updateJSON = Wizardry.updateJSON, dependencies = "required-after:forge@[14.23.5.2847,);after:jei@[4.15.0,);after:baubles@[1.5.2,);after:antiqueatlas@[4.6,)") public class Wizardry { /** Wizardry's mod ID. */ public static final String MODID = "ebwizardry"; /** Wizardry's mod name, in readable form. */ public static final String NAME = "Electroblob's Wizardry"; /** * The version number for this version of wizardry. The following system is used for version numbers: *

*
[major Minecraft version].[major mod version].[minor mod version/patch] *

*
The major mod version is consistent across Minecraft versions, i.e. Wizardry 1.1 has the same * features as Wizardry 2.1, but they are for different versions of Minecraft and have separate minor versioning. * 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft * 1.11.x versions, and so on. */ public static final String VERSION = "4.3.7"; /** * Json file used by Forge's built-in update checker. * Used by the in-game mod menu to show that green icon whenever a newer version is available of the mod. */ public static final String updateJSON = "https://github.com/Electroblob77/Wizardry/blob/1.12.2/.forge/update.json"; // IDEA: Triggering of inbuilt Forge events in relevant places? // IDEA: Abstract the vanilla particles behind the particle builder // TODO: Have particles obey Minecraft's particle setting where appropriate // (see https://github.com/RootsTeam/Embers/blob/master/src/main/java/teamroots/embers/particle/ParticleUtil.java) // TODO: TileEntityArcaneWorkbench needs looking at, esp. regarding inventory and markDirty /** Static instance of the {@link Settings} object for Wizardry. */ public static final Settings settings = new Settings(); /** Static instance of the {@link Logger} object for Wizardry. *

* Logging conventions for wizardry (only these levels are used currently): *

* - ERROR: Anything that threw an exception; may or may not crash the game.
* - WARN: Anything that isn't supposed to happen during normal operation, but didn't throw an exception.
* - INFO: Anything that might happen during normal mod operation that the user needs to know about. */ public static Logger logger; /** A {@link File} object representing wizardry's config folder, {@code config/ebwizardry}). As of wizardry 4.2.4, * this folder contains the main config file and the global spell properties folder, if used. */ public static File configDirectory; public static boolean tisTheSeason; // The instance of wizardry that Forge uses. @Instance(Wizardry.MODID) public static Wizardry instance; // Location of the proxy code, used by Forge. @SidedProxy(clientSide = "electroblob.wizardry.client.ClientProxy", serverSide = "electroblob.wizardry.CommonProxy") public static CommonProxy proxy; @EventHandler public void preInit(FMLPreInitializationEvent event){ logger = event.getModLog(); proxy.registerResourceReloadListeners(); configDirectory = new File(event.getModConfigurationDirectory(), Wizardry.MODID); settings.initConfig(event); Calendar calendar = Calendar.getInstance(); tisTheSeason = calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DAY_OF_MONTH) >= 24 && calendar.get(Calendar.DAY_OF_MONTH) <= 26; // Capabilities WizardData.register(); DispenserCastingData.register(); // Register things that don't have registries WizardryBlocks.registerTileEntities(); WizardryLoot.register(); WizardryAdvancementTriggers.register(); Forfeit.register(); BlockBookshelf.registerStandardBookModelTextures(); // Client-side stuff (via proxies) proxy.registerRenderers(); proxy.registerKeyBindings(); // Commented out for 4.2.3 to get rid of the sound bug, reinstate once a fix is found. WizardrySounds.SPELLS = SoundCategory.PLAYERS;//CustomSoundCategory.add(Wizardry.MODID + "_spells"); WizardryBaublesIntegration.init(); WizardryAntiqueAtlasIntegration.init(); } @EventHandler public void init(FMLInitializationEvent event){ settings.initConfigExtras(); // World generators // Weight is a misnomer, it's actually the priority (where lower numbers get generated first) // Literally nothing on typical 'weight' values here, there isn't even an upper limit // Examples I've managed to find: // - Tinker's construct slime islands use 25 GameRegistry.registerWorldGenerator(new WorldGenCrystalOre(), 0); GameRegistry.registerWorldGenerator(new WorldGenCrystalFlower(), 50); GameRegistry.registerWorldGenerator(new WorldGenWizardTower(), 20); GameRegistry.registerWorldGenerator(new WorldGenObelisk(), 20); GameRegistry.registerWorldGenerator(new WorldGenShrine(), 20); GameRegistry.registerWorldGenerator(new WorldGenLibraryRuins(), 20); GameRegistry.registerWorldGenerator(new WorldGenUndergroundLibraryRuins(), 20); // This is for the config change and missing mappings events MinecraftForge.EVENT_BUS.register(instance); // Since there's already an instance we might as well use it NetworkRegistry.INSTANCE.registerGuiHandler(this, new WizardryGuiHandler()); WizardryPacketHandler.initPackets(); // Post-registry extras BlockBookshelf.compileBookModelTextures(); ContainerBookshelf.initDefaultBookItems(); WizardryItems.registerDispenseBehaviours(); WizardryItems.registerBannerPatterns(); WandHelper.populateUpgradeMap(); Spell.registry.forEach(Spell::init); SpellProperties.init(); // Client-side stuff (via proxies) proxy.initGuiBits(); proxy.registerParticles(); proxy.registerSoundEventListener(); } @EventHandler public void postInit(FMLPostInitializationEvent event){ proxy.initialiseLayers(); proxy.initialiseAnimations(); SpellNetworkIDSorter.init(); } @EventHandler public void serverStarting(FMLServerStartingEvent event){ event.registerServerCommand(new CommandCastSpell()); event.registerServerCommand(new CommandSetAlly()); event.registerServerCommand(new CommandViewAllies()); event.registerServerCommand(new CommandDiscoverSpell()); } @SubscribeEvent public void onConfigChanged(net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent event){ if(event.getModID().equals(Wizardry.MODID)){ settings.saveConfigChanges(); // All of the synchronised settings require a world restart anyway so don't need syncing, except for the // donor perks which have special behaviour (since we have to update everyone when a donor logs in anyway, // we might as well reuse the packet and let them change the setting mid-game) if(event.isWorldRunning() && DonationPerksHandler.isDonor(proxy.getThePlayer())){ DonationPerksHandler.sendToServer(proxy.getThePlayer()); } } } // 2.1 changed some item ids, so this fixes them for existing worlds // Nobody updates minecraft versions when using mods, but I may as well leave this here just in case. @SubscribeEvent public static void onMissingItemMappingEvent(RegistryEvent.MissingMappings event){ // Just get, not getAll, since the mod id didn't change! for(RegistryEvent.MissingMappings.Mapping mapping : event.getAllMappings()){ if(mapping.key.getNamespace().equals(Wizardry.MODID)){ Item replacement; switch(mapping.key.getPath()){ case "wand_basic": replacement = WizardryItems.magic_wand; break; case "wand_basic_fire": replacement = WizardryItems.novice_fire_wand; break; case "wand_basic_ice": replacement = WizardryItems.novice_ice_wand; break; case "wand_basic_lightning": replacement = WizardryItems.novice_lightning_wand; break; case "wand_basic_necromancy": replacement = WizardryItems.novice_necromancy_wand; break; case "wand_basic_earth": replacement = WizardryItems.novice_earth_wand; break; case "wand_basic_sorcery": replacement = WizardryItems.novice_sorcery_wand; break; case "wand_basic_healing": replacement = WizardryItems.novice_healing_wand; break; case "basic_fire_wand": replacement = WizardryItems.novice_fire_wand; break; case "basic_ice_wand": replacement = WizardryItems.novice_ice_wand; break; case "basic_lightning_wand": replacement = WizardryItems.novice_lightning_wand; break; case "basic_necromancy_wand": replacement = WizardryItems.novice_necromancy_wand; break; case "basic_earth_wand": replacement = WizardryItems.novice_earth_wand; break; case "basic_sorcery_wand": replacement = WizardryItems.novice_sorcery_wand; break; case "basic_healing_wand": replacement = WizardryItems.novice_healing_wand; break; case "wand_apprentice": replacement = WizardryItems.apprentice_wand; break; case "wand_apprentice_fire": replacement = WizardryItems.apprentice_fire_wand; break; case "wand_apprentice_ice": replacement = WizardryItems.apprentice_ice_wand; break; case "wand_apprentice_lightning": replacement = WizardryItems.apprentice_lightning_wand; break; case "wand_apprentice_necromancy": replacement = WizardryItems.apprentice_necromancy_wand; break; case "wand_apprentice_earth": replacement = WizardryItems.apprentice_earth_wand; break; case "wand_apprentice_sorcery": replacement = WizardryItems.apprentice_sorcery_wand; break; case "wand_apprentice_healing": replacement = WizardryItems.apprentice_healing_wand; break; case "wand_advanced": replacement = WizardryItems.advanced_wand; break; case "wand_advanced_fire": replacement = WizardryItems.advanced_fire_wand; break; case "wand_advanced_ice": replacement = WizardryItems.advanced_ice_wand; break; case "wand_advanced_lightning": replacement = WizardryItems.advanced_lightning_wand; break; case "wand_advanced_necromancy": replacement = WizardryItems.advanced_necromancy_wand; break; case "wand_advanced_earth": replacement = WizardryItems.advanced_earth_wand; break; case "wand_advanced_sorcery": replacement = WizardryItems.advanced_sorcery_wand; break; case "wand_advanced_healing": replacement = WizardryItems.advanced_healing_wand; break; case "wand_master": replacement = WizardryItems.master_wand; break; case "wand_master_fire": replacement = WizardryItems.master_fire_wand; break; case "wand_master_ice": replacement = WizardryItems.master_ice_wand; break; case "wand_master_lightning": replacement = WizardryItems.master_lightning_wand; break; case "wand_master_necromancy": replacement = WizardryItems.master_necromancy_wand; break; case "wand_master_earth": replacement = WizardryItems.master_earth_wand; break; case "wand_master_sorcery": replacement = WizardryItems.master_sorcery_wand; break; case "wand_master_healing": replacement = WizardryItems.master_healing_wand; break; case "upgrade_storage": replacement = WizardryItems.storage_upgrade; break; case "upgrade_siphon": replacement = WizardryItems.siphon_upgrade; break; case "upgrade_condenser": replacement = WizardryItems.condenser_upgrade; break; case "upgrade_range": replacement = WizardryItems.range_upgrade; break; case "upgrade_duration": replacement = WizardryItems.duration_upgrade; break; case "upgrade_cooldown": replacement = WizardryItems.cooldown_upgrade; break; case "upgrade_blast": replacement = WizardryItems.blast_upgrade; break; case "upgrade_attunement": replacement = WizardryItems.attunement_upgrade; break; // If it didn't match any of the ones that changed, do nothing. default: return; } // No need to log, Forge does that. mapping.remap(replacement); } } } @SubscribeEvent public static void onMissingSpellMappingEvent(RegistryEvent.MissingMappings event){ for(RegistryEvent.MissingMappings.Mapping mapping : event.getAllMappings()){ if(mapping.key.getNamespace().equals(Wizardry.MODID)){ if(mapping.key.getPath().equals("firestorm")) mapping.remap(Spells.fire_breath); } } } }