From 95b27f490c097aa0817779d7d30a7644ebda33b0 Mon Sep 17 00:00:00 2001 From: yueh Date: Sun, 8 Oct 2017 17:33:06 +0200 Subject: [PATCH] Added Registry for customized charger rates. (#3139) * Added Registry for customized charger rates. * Added rates for all chargable items/block. * Charger and Inscriber now store 1.6k AE each instead of 1.5k * A crank applies 160 AE instead of 150 * Charged certus now requires 1.6k instead of 1.5k --- .../appeng/api/features/IChargerRegistry.java | 84 +++++++++++++ .../api/features/IRegistryContainer.java | 8 +- src/main/java/appeng/core/Registration.java | 16 ++- .../registries/RegistryContainer.java | 12 +- .../registries/charger/ChargerRegistry.java | 75 ++++++++++++ .../java/appeng/tile/misc/TileCharger.java | 110 +++++++++++------- .../java/appeng/tile/misc/TileInscriber.java | 2 +- 7 files changed, 257 insertions(+), 50 deletions(-) create mode 100644 src/api/java/appeng/api/features/IChargerRegistry.java create mode 100644 src/main/java/appeng/core/features/registries/charger/ChargerRegistry.java diff --git a/src/api/java/appeng/api/features/IChargerRegistry.java b/src/api/java/appeng/api/features/IChargerRegistry.java new file mode 100644 index 000000000..b49c3424f --- /dev/null +++ b/src/api/java/appeng/api/features/IChargerRegistry.java @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017 AlgorithmX2 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package appeng.api.features; + + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +import net.minecraft.item.Item; + +import appeng.api.implementations.items.IAEItemPowerStorage; + + +/** + * A registry to allow mapping {@link Item}s to a specific charge rate when being placed inside a charger. + * + * The registry is used in favor of an additional method for {@link IAEItemPowerStorage} with a fixed value per item. + * This allows more flexibility for other charger like machines to choose their own values when needed. + * + * There is no guarantee that this is charged per tick, it only represents the value per operation. + * By default this is one charging operation every 10 ticks in case of an AE2 charger. + * + * @author yueh + * @version rv5 + * @since rv5 + */ +public interface IChargerRegistry +{ + + /** + * Fetch a charge rate for a specific item. + * + * The specific item does not need to have a mapping registered at all. + * In this case it will use a default value of 160 AE. + * + * @param item A {@link Item} implementing {@link IAEItemPowerStorage}. + * @return custom rate or default of 160 + */ + @Nonnegative + double getChargeRate( @Nonnull Item item ); + + /** + * Register a custom charge rate for a specific item. + * + * Capped at 16000 to avoid extracting too much energy from a network for each operation. + * This is done silently without any feedback or exception. + * Further the cap is not fixed, it can change at any time in the future should power issues arise. + * + * @param item A {@link Item} implementing {@link IAEItemPowerStorage}. + * @param chargeRate the custom rate, must be > 0, capped to 16000d + */ + void addChargeRate( @Nonnull Item item, @Nonnegative double chargeRate ); + + /** + * Remove the custom rate for a specific item. + * + * It will revert to the default value afterwards. + * + * @param item A {@link Item} implementing {@link IAEItemPowerStorage}. + */ + void removeChargeRate( @Nonnull Item item ); + +} diff --git a/src/api/java/appeng/api/features/IRegistryContainer.java b/src/api/java/appeng/api/features/IRegistryContainer.java index 393187f97..e3780c0dd 100644 --- a/src/api/java/appeng/api/features/IRegistryContainer.java +++ b/src/api/java/appeng/api/features/IRegistryContainer.java @@ -34,7 +34,8 @@ import appeng.api.storage.ICellRegistry; /** * @author AlgorithmX2 * @author thatsIch - * @version rv2 + * @author yueh + * @version rv5 * @since rv0 */ @AEInjectable @@ -76,6 +77,11 @@ public interface IRegistryContainer */ IInscriberRegistry inscriber(); + /** + * Manage charger via API + */ + IChargerRegistry charger(); + /** * get access to the locatable registry */ diff --git a/src/main/java/appeng/core/Registration.java b/src/main/java/appeng/core/Registration.java index ed4bf952e..efa6eeafb 100644 --- a/src/main/java/appeng/core/Registration.java +++ b/src/main/java/appeng/core/Registration.java @@ -460,10 +460,18 @@ final class Registration // Inscriber Upgrades.SPEED.registerItem( blocks.inscriber(), 3 ); - items.wirelessTerminal().maybeItem().ifPresent( terminal -> - { - registries.wireless().registerWirelessHandler( (IWirelessTermHandler) terminal ); - } ); + // Wireless Terminal Handler + items.wirelessTerminal().maybeItem().ifPresent( terminal -> registries.wireless().registerWirelessHandler( (IWirelessTermHandler) terminal ) ); + + // Charge Rates + items.chargedStaff().maybeItem().ifPresent( chargedStaff -> registries.charger().addChargeRate( chargedStaff, 320d ) ); + items.portableCell().maybeItem().ifPresent( chargedStaff -> registries.charger().addChargeRate( chargedStaff, 800d ) ); + items.colorApplicator().maybeItem().ifPresent( colorApplicator -> registries.charger().addChargeRate( colorApplicator, 800d ) ); + items.wirelessTerminal().maybeItem().ifPresent( terminal -> registries.charger().addChargeRate( terminal, 8000d ) ); + items.entropyManipulator().maybeItem().ifPresent( entropyManipulator -> registries.charger().addChargeRate( entropyManipulator, 8000d ) ); + items.massCannon().maybeItem().ifPresent( massCannon -> registries.charger().addChargeRate( massCannon, 8000d ) ); + blocks.energyCell().maybeItem().ifPresent( cell -> registries.charger().addChargeRate( cell, 8000d ) ); + blocks.energyCellDense().maybeItem().ifPresent( cell -> registries.charger().addChargeRate( cell, 16000d ) ); // add villager trading to black smiths for a few basic materials if( AEConfig.instance().isFeatureEnabled( AEFeature.VILLAGER_TRADING ) ) diff --git a/src/main/java/appeng/core/features/registries/RegistryContainer.java b/src/main/java/appeng/core/features/registries/RegistryContainer.java index 5ddade926..14678d0ec 100644 --- a/src/main/java/appeng/core/features/registries/RegistryContainer.java +++ b/src/main/java/appeng/core/features/registries/RegistryContainer.java @@ -19,6 +19,7 @@ package appeng.core.features.registries; +import appeng.api.features.IChargerRegistry; import appeng.api.features.IGrinderRegistry; import appeng.api.features.IInscriberRegistry; import appeng.api.features.ILocatableRegistry; @@ -35,6 +36,7 @@ import appeng.api.networking.IGridCacheRegistry; import appeng.api.parts.IPartModels; import appeng.api.storage.ICellRegistry; import appeng.core.features.registries.cell.CellRegistry; +import appeng.core.features.registries.charger.ChargerRegistry; import appeng.core.features.registries.grinder.GrinderRecipeManager; import appeng.core.features.registries.inscriber.InscriberRegistry; @@ -44,13 +46,15 @@ import appeng.core.features.registries.inscriber.InscriberRegistry; * * @author AlgorithmX2 * @author thatsIch - * @version rv2 + * @author yueh + * @version rv5 * @since rv0 */ public class RegistryContainer implements IRegistryContainer { private final IGrinderRegistry grinder = new GrinderRecipeManager(); private final IInscriberRegistry inscriber = new InscriberRegistry(); + private final IChargerRegistry charger = new ChargerRegistry(); private final ICellRegistry cell = new CellRegistry(); private final ILocatableRegistry locatable = new LocatableRegistry(); private final ISpecialComparisonRegistry comparison = new SpecialComparisonRegistry(); @@ -105,6 +109,12 @@ public class RegistryContainer implements IRegistryContainer return this.inscriber; } + @Override + public IChargerRegistry charger() + { + return this.charger; + } + @Override public ILocatableRegistry locatable() { diff --git a/src/main/java/appeng/core/features/registries/charger/ChargerRegistry.java b/src/main/java/appeng/core/features/registries/charger/ChargerRegistry.java new file mode 100644 index 000000000..743252db4 --- /dev/null +++ b/src/main/java/appeng/core/features/registries/charger/ChargerRegistry.java @@ -0,0 +1,75 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2017, 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.features.registries.charger; + + +import java.util.IdentityHashMap; +import java.util.Map; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +import com.google.common.base.Preconditions; + +import net.minecraft.item.Item; + +import appeng.api.features.IChargerRegistry; + + +public class ChargerRegistry implements IChargerRegistry +{ + private static final double DEFAULT_CHARGE_RATE = 160d; + private static final double CAPPED_CHARGE_RATE = 16000d; + + private final Map chargeRates; + + public ChargerRegistry() + { + this.chargeRates = new IdentityHashMap<>(); + } + + @Override + @Nonnegative + public double getChargeRate( @Nonnull Item item ) + { + Preconditions.checkNotNull( item ); + + return this.chargeRates.getOrDefault( item, DEFAULT_CHARGE_RATE ); + } + + @Override + public void addChargeRate( @Nonnull Item item, @Nonnegative double value ) + { + Preconditions.checkNotNull( item ); + Preconditions.checkArgument( value > 0d ); + + final double cappedValue = Math.min( value, CAPPED_CHARGE_RATE ); + + this.chargeRates.put( item, cappedValue ); + } + + @Override + public void removeChargeRate( @Nonnull Item item ) + { + Preconditions.checkNotNull( item ); + + this.chargeRates.remove( item ); + } + +} diff --git a/src/main/java/appeng/tile/misc/TileCharger.java b/src/main/java/appeng/tile/misc/TileCharger.java index 8dbaec7e5..c83399397 100644 --- a/src/main/java/appeng/tile/misc/TileCharger.java +++ b/src/main/java/appeng/tile/misc/TileCharger.java @@ -59,17 +59,17 @@ import appeng.util.item.AEItemStack; public class TileCharger extends AENetworkPowerTile implements ICrankable, IGridTickable { - private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 1, 1, new ChargerInvFilter() ); - private int tickTickTimer = 0; + private static final int POWER_MAXIMUM_AMOUNT = 1600; + private static final int POWER_THRESHOLD = POWER_MAXIMUM_AMOUNT - 1; + private static final int POWER_PER_CRANK_TURN = 160; - private int lastUpdate = 0; - private boolean requiresUpdate = false; + private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 1, 1, new ChargerInvFilter() ); public TileCharger() { this.getProxy().setValidSides( EnumSet.noneOf( EnumFacing.class ) ); this.getProxy().setFlags(); - this.setInternalMaxPower( 1500 ); + this.setInternalMaxPower( POWER_MAXIMUM_AMOUNT ); this.getProxy().setIdlePowerUsage( 0 ); } @@ -130,16 +130,16 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid @Override public void applyTurn() { - this.injectExternalPower( PowerUnits.AE, 150, Actionable.MODULATE ); + this.injectExternalPower( PowerUnits.AE, POWER_PER_CRANK_TURN, Actionable.MODULATE ); final ItemStack myItem = this.inv.getStackInSlot( 0 ); - if( this.getInternalCurrentPower() > 1499 ) + if( this.getInternalCurrentPower() > POWER_THRESHOLD ) { final IMaterials materials = AEApi.instance().definitions().materials(); if( materials.certusQuartzCrystal().isSameAs( myItem ) ) { - this.extractAEPower( this.getInternalMaxPower(), Actionable.MODULATE, PowerMultiplier.CONFIG );// 1500 + this.extractAEPower( this.getInternalMaxPower(), Actionable.MODULATE, PowerMultiplier.CONFIG ); materials.certusQuartzCrystalCharged().maybeStack( myItem.getCount() ).ifPresent( charged -> this.inv.setStackInSlot( 0, charged ) ); } @@ -215,55 +215,79 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid private boolean doWork() { final ItemStack myItem = this.inv.getStackInSlot( 0 ); + boolean changed = false; + + if( !myItem.isEmpty() ) + { + final IMaterials materials = AEApi.instance().definitions().materials(); + + if( Platform.isChargeable( myItem ) ) + { + final IAEItemPowerStorage ps = (IAEItemPowerStorage) myItem.getItem(); + + if( ps.getAEMaxPower( myItem ) > ps.getAECurrentPower( myItem ) ) + { + final double chargeRate = AEApi.instance().registries().charger().getChargeRate( myItem.getItem() ); + + double extractedAmount = this.extractAEPower( chargeRate, Actionable.MODULATE, PowerMultiplier.CONFIG ); + + final double missingChargeRate = chargeRate - extractedAmount; + final double missingAEPower = ps.getAEMaxPower( myItem ) - ps.getAECurrentPower( myItem ); + final double toExtract = Math.min( missingChargeRate, missingAEPower ); + + try + { + extractedAmount += this.getProxy().getEnergy().extractAEPower( toExtract, Actionable.MODULATE, PowerMultiplier.ONE ); + } + catch( GridAccessException e1 ) + { + // Ignore. + } + + if( extractedAmount > 0 ) + { + final double adjustment = ps.injectAEPower( myItem, extractedAmount, Actionable.MODULATE ); + + this.setInternalCurrentPower( this.getInternalCurrentPower() + adjustment ); + + changed = true; + } + } + } + else if( this.getInternalCurrentPower() > POWER_THRESHOLD && materials.certusQuartzCrystal().isSameAs( myItem ) ) + { + if( Platform.getRandomFloat() > 0.8f ) // simulate wait + { + this.extractAEPower( this.getInternalMaxPower(), Actionable.MODULATE, PowerMultiplier.CONFIG ); + + materials.certusQuartzCrystalCharged().maybeStack( myItem.getCount() ).ifPresent( charged -> this.inv.setStackInSlot( 0, charged ) ); + + changed = true; + } + } + } // charge from the network! - if( this.getInternalCurrentPower() < 1499 ) + if( this.getInternalCurrentPower() < POWER_THRESHOLD ) { try { - this.injectExternalPower( PowerUnits.AE, this.getProxy().getEnergy().extractAEPower( Math.min( 500.0, 1500.0 - this.getInternalCurrentPower() ), - Actionable.MODULATE, PowerMultiplier.ONE ), Actionable.MODULATE ); + final double toExtract = Math.min( 800.0, this.getInternalMaxPower() - this.getInternalCurrentPower() ); + final double extracted = this.getProxy().getEnergy().extractAEPower( toExtract, Actionable.MODULATE, PowerMultiplier.ONE ); + + this.injectExternalPower( PowerUnits.AE, extracted, Actionable.MODULATE ); } catch( final GridAccessException e ) { // continue! } - return true; + changed = true; } - if( myItem.isEmpty() ) + if( changed ) { - return false; - } - - final IMaterials materials = AEApi.instance().definitions().materials(); - - if( this.getInternalCurrentPower() > 149 && Platform.isChargeable( myItem ) ) - { - final IAEItemPowerStorage ps = (IAEItemPowerStorage) myItem.getItem(); - if( ps.getAEMaxPower( myItem ) > ps.getAECurrentPower( myItem ) ) - { - final double oldPower = this.getInternalCurrentPower(); - - final double adjustment = ps.injectAEPower( myItem, this.extractAEPower( 150.0, Actionable.MODULATE, PowerMultiplier.CONFIG ), - Actionable.MODULATE ); - this.setInternalCurrentPower( this.getInternalCurrentPower() + adjustment ); - - if( oldPower > this.getInternalCurrentPower() ) - { - this.markForUpdate(); - } - } - } - else if( this.getInternalCurrentPower() > 1499 && materials.certusQuartzCrystal().isSameAs( myItem ) ) - { - if( Platform.getRandomFloat() > 0.8f ) // simulate wait - { - this.extractAEPower( this.getInternalMaxPower(), Actionable.MODULATE, PowerMultiplier.CONFIG );// 1500 - - materials.certusQuartzCrystalCharged().maybeStack( myItem.getCount() ).ifPresent( charged -> this.inv.setStackInSlot( 0, charged ) ); - } + this.markForUpdate(); } return true; diff --git a/src/main/java/appeng/tile/misc/TileInscriber.java b/src/main/java/appeng/tile/misc/TileInscriber.java index 464ab4f2f..4a9d98693 100644 --- a/src/main/java/appeng/tile/misc/TileInscriber.java +++ b/src/main/java/appeng/tile/misc/TileInscriber.java @@ -103,7 +103,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable, public TileInscriber() { this.getProxy().setValidSides( EnumSet.noneOf( EnumFacing.class ) ); - this.setInternalMaxPower( 1500 ); + this.setInternalMaxPower( 1600 ); this.getProxy().setIdlePowerUsage( 0 ); this.settings = new ConfigManager( this );