From 48f9ca1fcb4e2927d72c310c06b3d016784548fb Mon Sep 17 00:00:00 2001 From: thatsIch Date: Fri, 19 Dec 2014 12:28:41 +0100 Subject: [PATCH] Fixes #604 Crash on crafting The AE2 has in the contract that the item field in an IAEItemDefinition can be null due to the fact, if a special item is deactivated. This needs to be checked. The base code was enhanced through Javadoc and split in responsibilities --- src/main/java/appeng/core/Registration.java | 4 +- .../stats/AchievementCraftingHandler.java | 71 +++++++++ .../core/stats/AchievementHierarchy.java | 61 ++++++++ .../core/stats/AchievementPickupHandler.java | 63 ++++++++ .../core/stats/PlayerDifferentiator.java | 48 ++++++ .../core/stats/PlayerStatsRegistration.java | 145 ++++++------------ 6 files changed, 293 insertions(+), 99 deletions(-) create mode 100644 src/main/java/appeng/core/stats/AchievementCraftingHandler.java create mode 100644 src/main/java/appeng/core/stats/AchievementHierarchy.java create mode 100644 src/main/java/appeng/core/stats/AchievementPickupHandler.java create mode 100644 src/main/java/appeng/core/stats/PlayerDifferentiator.java diff --git a/src/main/java/appeng/core/Registration.java b/src/main/java/appeng/core/Registration.java index 265fea92..6181a231 100644 --- a/src/main/java/appeng/core/Registration.java +++ b/src/main/java/appeng/core/Registration.java @@ -588,7 +588,9 @@ public class Registration recipeHandler.injectRecipes(); - PlayerStatsRegistration.instance.init(); + final PlayerStatsRegistration registration = new PlayerStatsRegistration( FMLCommonHandler.instance().bus(), AEConfig.instance ); + registration.registerAchievementHandlers(); + registration.registerAchievements(); if ( AEConfig.instance.isFeatureEnabled( AEFeature.enableDisassemblyCrafting ) ) CraftingManager.getInstance().getRecipeList().add( new DisassembleRecipe() ); diff --git a/src/main/java/appeng/core/stats/AchievementCraftingHandler.java b/src/main/java/appeng/core/stats/AchievementCraftingHandler.java new file mode 100644 index 00000000..32f21f3f --- /dev/null +++ b/src/main/java/appeng/core/stats/AchievementCraftingHandler.java @@ -0,0 +1,71 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.core.stats; + + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; + +import appeng.util.Platform; + + +/** + * handles the achievement when an {@link net.minecraft.item.Item} is crafted by a player. + * The achievement is only added if its a real {@link net.minecraft.entity.player.EntityPlayer}. + * + * @author thatsIch + * @since rv2 + */ +public class AchievementCraftingHandler +{ + private final PlayerDifferentiator differentiator; + + public AchievementCraftingHandler( PlayerDifferentiator differentiator ) + { + this.differentiator = differentiator; + } + + @SubscribeEvent + public void onPlayerCraftingEvent( PlayerEvent.ItemCraftedEvent event ) + { + if ( this.differentiator.isNoPlayer( event.player ) || event.crafting == null ) + return; + + for ( Achievements achievement : Achievements.values() ) + { + switch ( achievement.type ) + { + case Craft: + if ( Platform.isSameItemPrecise( achievement.stack, event.crafting ) ) + { + achievement.addToPlayer( event.player ); + return; + } + break; + case CraftItem: + if ( achievement.stack != null && achievement.stack.getItem().getClass() == event.crafting.getItem().getClass() ) + { + achievement.addToPlayer( event.player ); + return; + } + default: + } + } + } +} diff --git a/src/main/java/appeng/core/stats/AchievementHierarchy.java b/src/main/java/appeng/core/stats/AchievementHierarchy.java new file mode 100644 index 00000000..3c07f684 --- /dev/null +++ b/src/main/java/appeng/core/stats/AchievementHierarchy.java @@ -0,0 +1,61 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.core.stats; + + +/** + * Hierarchy of the AE2 achievements + * + * @author thatsIch + * @since rv2 + */ +public class AchievementHierarchy +{ + /** + * Setup hierarchy through assigning parents. + */ + public void registerAchievementHierarchy() + { + Achievements.Presses.setParent( Achievements.Compass ); + + Achievements.Fluix.setParent( Achievements.ChargedQuartz ); + + Achievements.Charger.setParent( Achievements.Fluix ); + + Achievements.CrystalGrowthAccelerator.setParent( Achievements.Charger ); + + Achievements.GlassCable.setParent( Achievements.Charger ); + + Achievements.SpatialIOExplorer.setParent( Achievements.SpatialIO ); + + Achievements.IOPort.setParent( Achievements.StorageCell ); + + Achievements.PatternTerminal.setParent( Achievements.CraftingTerminal ); + + Achievements.Controller.setParent( Achievements.Networking1 ); + + Achievements.Networking2.setParent( Achievements.Controller ); + + Achievements.Networking3.setParent( Achievements.Networking2 ); + + Achievements.P2P.setParent( Achievements.Controller ); + + Achievements.Recursive.setParent( Achievements.Controller ); + } +} diff --git a/src/main/java/appeng/core/stats/AchievementPickupHandler.java b/src/main/java/appeng/core/stats/AchievementPickupHandler.java new file mode 100644 index 00000000..29dfbd38 --- /dev/null +++ b/src/main/java/appeng/core/stats/AchievementPickupHandler.java @@ -0,0 +1,63 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.core.stats; + + +import net.minecraft.item.ItemStack; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; + +import appeng.util.Platform; + + +/** + * handles the achievement when an {@link net.minecraft.item.Item} is picked up by a player. + * The achievement is only added if its a real {@link net.minecraft.entity.player.EntityPlayer}. + * + * @author thatsIch + * @since rv2 + */ +public class AchievementPickupHandler +{ + private final PlayerDifferentiator differentiator; + + public AchievementPickupHandler( PlayerDifferentiator differentiator ) + { + this.differentiator = differentiator; + } + + @SubscribeEvent + public void onItemPickUp( PlayerEvent.ItemPickupEvent event ) + { + if ( this.differentiator.isNoPlayer( event.player ) || event.pickedUp == null || event.pickedUp.getEntityItem() == null ) + return; + + ItemStack is = event.pickedUp.getEntityItem(); + + for ( Achievements achievement : Achievements.values() ) + { + if ( achievement.type == AchievementType.Pickup && Platform.isSameItemPrecise( achievement.stack, is ) ) + { + achievement.addToPlayer( event.player ); + return; + } + } + } +} diff --git a/src/main/java/appeng/core/stats/PlayerDifferentiator.java b/src/main/java/appeng/core/stats/PlayerDifferentiator.java new file mode 100644 index 00000000..ebb7d92c --- /dev/null +++ b/src/main/java/appeng/core/stats/PlayerDifferentiator.java @@ -0,0 +1,48 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * + * Applied Energistics 2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Applied Energistics 2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Applied Energistics 2. If not, see . + */ + +package appeng.core.stats; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.common.util.FakePlayer; + + +/** + * Can differentiate if a {@link net.minecraft.entity.player.EntityPlayer} is a real player or not + * + * @author thatsIch + * @since rv2 + */ +public class PlayerDifferentiator +{ + /** + * Can determine if an {@link net.minecraft.entity.player.EntityPlayer} is not a real player. + * This is based on if the {@param player} is: + * - null + * - dead + * - fake + * + * @param player to be checked player + * @return true if {@param player} is not a real player + */ + public boolean isNoPlayer( EntityPlayer player ) + { + return player == null || player.isDead || player instanceof FakePlayer; + } +} diff --git a/src/main/java/appeng/core/stats/PlayerStatsRegistration.java b/src/main/java/appeng/core/stats/PlayerStatsRegistration.java index 597bbca5..b8499b1e 100644 --- a/src/main/java/appeng/core/stats/PlayerStatsRegistration.java +++ b/src/main/java/appeng/core/stats/PlayerStatsRegistration.java @@ -18,125 +18,74 @@ package appeng.core.stats; + import java.util.ArrayList; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; import net.minecraft.stats.Achievement; import net.minecraftforge.common.AchievementPage; -import net.minecraftforge.common.util.FakePlayer; + +import cpw.mods.fml.common.eventhandler.EventBus; + import appeng.core.AEConfig; import appeng.core.features.AEFeature; -import appeng.util.Platform; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.gameevent.PlayerEvent; + +/** + * Registers any items a player is picking up or is crafting. + * Registered items are added to the player stats. + * This will only happen if the {@link AEFeature#Achievements} feature is enabled. + */ public class PlayerStatsRegistration { + /** + * {@link cpw.mods.fml.common.eventhandler.EventBus} to which the handlers might get posted to depending if the feature is enabled + */ + private final EventBus bus; - public final static PlayerStatsRegistration instance = new PlayerStatsRegistration(); + /** + * is true if the {@link appeng.core.features.AEFeature#Achievements} is enabled in the {@param config} + */ + private final boolean isAchievementFeatureEnabled; - AchievementPage ae2AchievementPage; - - @SubscribeEvent - public void onCrafting(PlayerEvent.ItemCraftedEvent event) + /** + * Constructs a {@link appeng.core.stats.PlayerStatsRegistration} with an {@link cpw.mods.fml.common.eventhandler.EventBus} and {@link appeng.core.AEConfig}. + * + * @param bus {@see #bus} + * @param config {@link appeng.core.AEConfig} which is used to determine if the {@link appeng.core.features.AEFeature#Achievements} is enabled + */ + public PlayerStatsRegistration( EventBus bus, AEConfig config ) { - if ( notPlayer( event.player ) || event.crafting == null ) - return; - - for (Achievements a : Achievements.values()) - { - switch (a.type) - { - case Craft: - if ( Platform.isSameItemPrecise( a.stack, event.crafting ) ) - { - a.addToPlayer( event.player ); - return; - } - break; - case CraftItem: - if ( a.stack.getItem().getClass() == event.crafting.getItem().getClass() ) - { - a.addToPlayer( event.player ); - return; - } - default: - } - } - } - - @SubscribeEvent - public void onCrafting(PlayerEvent.ItemPickupEvent event) - { - if ( notPlayer( event.player ) || event.pickedUp == null || event.pickedUp.getEntityItem() == null ) - return; - - ItemStack is = event.pickedUp.getEntityItem(); - - for (Achievements a : Achievements.values()) - { - switch (a.type) - { - case Pickup: - if ( Platform.isSameItemPrecise( a.stack, is ) ) - { - a.addToPlayer( event.player ); - return; - } - default: - } - } - } - - private boolean notPlayer(EntityPlayer player) - { - if ( player == null || player.isDead || player instanceof FakePlayer ) - return true; - return false; + this.bus = bus; + this.isAchievementFeatureEnabled = config.isFeatureEnabled( AEFeature.Achievements ); } /** - * Assign Parents and hierarchy. + * Registers the {@link appeng.core.stats.AchievementCraftingHandler} and {@link appeng.core.stats.AchievementPickupHandler} to the {@link #bus} if {@link #isAchievementFeatureEnabled} is true. */ - private void initHierarchy() + public void registerAchievementHandlers() { - Achievements.Presses.setParent( Achievements.Compass ); + if ( this.isAchievementFeatureEnabled ) + { + final PlayerDifferentiator differentiator = new PlayerDifferentiator(); + final AchievementCraftingHandler craftingHandler = new AchievementCraftingHandler( differentiator ); + final AchievementPickupHandler pickupHandler = new AchievementPickupHandler( differentiator ); - Achievements.Fluix.setParent( Achievements.ChargedQuartz ); - - Achievements.Charger.setParent( Achievements.Fluix ); - - Achievements.CrystalGrowthAccelerator.setParent( Achievements.Charger ); - - Achievements.GlassCable.setParent( Achievements.Charger ); - - Achievements.SpatialIOExplorer.setParent( Achievements.SpatialIO ); - - Achievements.IOPort.setParent( Achievements.StorageCell ); - - Achievements.PatternTerminal.setParent( Achievements.CraftingTerminal ); - - Achievements.Controller.setParent( Achievements.Networking1 ); - - Achievements.Networking2.setParent( Achievements.Controller ); - - Achievements.Networking3.setParent( Achievements.Networking2 ); - - Achievements.P2P.setParent( Achievements.Controller ); - - Achievements.Recursive.setParent( Achievements.Controller ); + this.bus.register( craftingHandler ); + this.bus.register( pickupHandler ); + } } - public void init() + /** + * Registers the {@link appeng.core.stats.AchievementHierarchy} and adds all {@link appeng.core.stats.Achievements} to a new {@link net.minecraftforge.common.AchievementPage}. + */ + public void registerAchievements() { - if ( AEConfig.instance.isFeatureEnabled( AEFeature.Achievements ) ) + if ( this.isAchievementFeatureEnabled ) { - FMLCommonHandler.instance().bus().register( this ); - initHierarchy(); + final AchievementHierarchy hierarchy = new AchievementHierarchy(); + hierarchy.registerAchievementHierarchy(); - for (Stats s : Stats.values()) + for ( Stats s : Stats.values() ) s.getStat(); /** @@ -144,14 +93,14 @@ public class PlayerStatsRegistration */ ArrayList list = new ArrayList(); - for (Achievements a : Achievements.values()) + for ( Achievements a : Achievements.values() ) { Achievement ach = a.getAchievement(); if ( ach != null ) list.add( ach ); } - ae2AchievementPage = new AchievementPage( "Applied Energistics 2", list.toArray( new Achievement[list.size()] ) ); + AchievementPage ae2AchievementPage = new AchievementPage( "Applied Energistics 2", list.toArray( new Achievement[list.size()] ) ); AchievementPage.registerAchievementPage( ae2AchievementPage ); } }