diff --git a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java index 2f4ac89b8..bcd2c6fdd 100644 --- a/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java +++ b/minecraft/1.7/src/main/java/nova/core/wrapper/mc/forge/v17/launcher/NovaMinecraft.java @@ -178,6 +178,7 @@ public void preInit(FMLPreInitializationEvent evt) { Game.blocks().init(); Game.items().init(); Game.entities().init(); + Game.fluids().init(); //Load preInit progressBar = ProgressManager.push("Pre-initializing NOVA wrappers", (novaModWrappers.isEmpty() ? 1 : novaModWrappers.size()) + novaWrappers.size()); diff --git a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java index cbb5ed302..6335072cc 100644 --- a/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java +++ b/minecraft/1.8/src/main/java/nova/core/wrapper/mc/forge/v18/launcher/NovaMinecraft.java @@ -183,6 +183,7 @@ public void preInit(FMLPreInitializationEvent evt) { Game.blocks().init(); Game.items().init(); Game.entities().init(); + Game.fluids().init(); //Load preInit progressBar = ProgressManager.push("Pre-initializing NOVA wrappers", (novaModWrappers.isEmpty() ? 1 : novaModWrappers.size()) + novaWrappers.size()); diff --git a/src/main/java/nova/core/component/fluid/Fluid.java b/src/main/java/nova/core/component/fluid/Fluid.java index 809e968ca..caeb4ecc7 100644 --- a/src/main/java/nova/core/component/fluid/Fluid.java +++ b/src/main/java/nova/core/component/fluid/Fluid.java @@ -21,6 +21,8 @@ package nova.core.component.fluid; import nova.core.block.BlockFactory; +import nova.core.component.exception.ComponentException; +import nova.core.component.misc.FactoryProvider; import nova.core.retention.Data; import nova.core.retention.Storable; import nova.core.retention.Store; @@ -29,11 +31,12 @@ import java.util.Optional; +// TODO: Should this extend ComponentProvider? public class Fluid implements Identifiable, Storable, Cloneable { /** * 1000 liters = 1 cubic meter */ - public static final int bucketVolume = 1000; + public static final int BUCKET_VOLUME = 1000; /** * Fluid amount is measured in liters. */ @@ -41,7 +44,7 @@ public class Fluid implements Identifiable, Storable, Cloneable { private int amount = 1; //TODO: Public instance variable is not good practice - public FluidFactory factory; + private FluidFactory factory = null; /** * @return Amount of fluid @@ -104,7 +107,7 @@ public Fluid withAmount(int amount) { * @return The block. There may be no block associated with this fluid. */ public Optional getBlockFactory() { - return Optional.empty(); + return Game.blocks().get(getID()); } @Override @@ -125,9 +128,25 @@ public boolean sameType(Fluid stack) { return stack.getID().equals(getID()); } + void initFactory(FluidFactory factory) { + if (this.factory == null) { + this.factory = factory; + } else { + throw new ComponentException("Attempt to add two components of the type %s to " + this, FactoryProvider.class); + } + } + + public final FluidFactory getFactory() { + if (factory != null) { + return factory; + } else { + throw new ComponentException("Attempt to get component that does not exist: %s", FactoryProvider.class); + } + } + @Override public final String getID() { - return factory.getID(); + return getFactory().getID(); } @Override diff --git a/src/main/java/nova/core/component/fluid/FluidFactory.java b/src/main/java/nova/core/component/fluid/FluidFactory.java index 2357716de..f36cdddc7 100644 --- a/src/main/java/nova/core/component/fluid/FluidFactory.java +++ b/src/main/java/nova/core/component/fluid/FluidFactory.java @@ -54,7 +54,7 @@ public FluidFactory(String id, Supplier constructor) { @Override public Fluid build() { Fluid build = super.build(); - build.factory = this; + build.initFactory(this); return build; } diff --git a/src/main/java/nova/core/component/fluid/FluidFilter.java b/src/main/java/nova/core/component/fluid/FluidFilter.java new file mode 100644 index 000000000..4261a86b5 --- /dev/null +++ b/src/main/java/nova/core/component/fluid/FluidFilter.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + +package nova.core.component.fluid; + +import java.util.function.Predicate; + +/** + * A filter that only accepts a specific sub-type of {@link Fluid}. For use with tanks. + * + * @author ExE Boss + */ +@FunctionalInterface +public interface FluidFilter extends Predicate { + + /** + * Returns an {@link FluidFilter} that accepts an {@link Fluid} of the same + * type as the provided. + * + * @param fluid + * @return FluidFilter + */ + static FluidFilter of(Fluid fluid) { + return fluid::sameType; + } + + /** + * Returns an {@link FluidFilter} that accepts an {@link Fluid} of the same + * type as provided. + * + * @param id + * @return FluidFilter + */ + static FluidFilter of(String id) { + return (other) -> id.equals(other.getID()); + } + + /** + * Accepts any {@link Fluid} that has a >= amount than provided. + * + * @param amount + * @return FluidFilter + */ + static FluidFilter of(int amount) { + return (other) -> other.amount() >= amount; + } +} diff --git a/src/main/java/nova/core/component/fluid/FluidHandler.java b/src/main/java/nova/core/component/fluid/FluidHandler.java index 6360835b9..847aa999c 100644 --- a/src/main/java/nova/core/component/fluid/FluidHandler.java +++ b/src/main/java/nova/core/component/fluid/FluidHandler.java @@ -1,44 +1,81 @@ /* - * Copyright (c) 2015 NOVA, All rights reserved. + * Copyright (c) 2017 NOVA, All rights reserved. * This library is free software, licensed under GNU Lesser General Public License version 3 * * This file is part of NOVA. * * NOVA is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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. * * NOVA 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with NOVA. If not, see . - */package nova.core.component.fluid; + */ +package nova.core.component.fluid; import nova.core.component.Component; -import nova.core.util.Direction; +import nova.core.retention.Storable; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Function; +import java.util.function.Predicate; /** - * @author Calclavia + * @author ExE Boss */ -public class FluidHandler extends Component { +public abstract class FluidHandler extends Component implements FluidIO, TankProvider, Storable { - public Set tanks = new HashSet<>(); - public Function> sidedTanks = direction -> tanks; + public static FluidHandler singleTank() { + return FluidHandlerSimple.simpleSingleTank(); + } - public FluidHandler() { + public static FluidHandler singleTank(int capacity) { + return FluidHandlerSimple.simpleSingleTank(capacity); } - public FluidHandler(Tank... tanks) { - this.tanks.addAll(Arrays.asList(tanks)); + public static FluidHandler singleTank(Predicate fluidFilter) { + return FluidHandlerSimple.simpleSingleTank(fluidFilter); } + public static FluidHandler singleTank(int capacity, Predicate fluidFilter) { + return FluidHandlerSimple.simpleSingleTank(capacity, fluidFilter); + } + + public static FluidHandler multiTank(Tank... tanks) { + return new FluidHandlerSimple(false, tanks); + } + + @Override + public int getFluidAmount() { + return getTanks().stream().mapToInt(Tank::getFluidAmount).sum(); + } + + @Override + public boolean isEmpty() { + return getTanks().isEmpty() || getTanks().stream().allMatch(Tank::isEmpty); + } + + @Override + public boolean hasFluid() { + return !getTanks().isEmpty() && getTanks().stream().anyMatch(Tank::hasFluid); + } + + @Override + public boolean hasFluidType(String fluidID) { + return !getTanks().isEmpty() && getTanks().stream().anyMatch(t -> t.hasFluidType(fluidID)); + } + + @Override + public boolean hasFluidType(Fluid sample) { + return !getTanks().isEmpty() && getTanks().stream().anyMatch(t -> t.hasFluidType(sample)); + } + + @Override + public boolean hasFluidType(FluidFactory sample) { + return !getTanks().isEmpty() && getTanks().stream().anyMatch(t -> t.hasFluidType(sample)); + } } diff --git a/src/main/java/nova/core/component/fluid/FluidHandlerSimple.java b/src/main/java/nova/core/component/fluid/FluidHandlerSimple.java new file mode 100644 index 000000000..26bbd18e4 --- /dev/null +++ b/src/main/java/nova/core/component/fluid/FluidHandlerSimple.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2015 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + +package nova.core.component.fluid; + +import nova.core.component.SidedComponent; +import nova.core.retention.Data; +import nova.core.retention.Storable; +import nova.core.retention.Store; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * A sided component that provides a fluid container. + * @author Calclavia + */ +@SidedComponent +public class FluidHandlerSimple extends FluidHandler implements Storable { + + protected Set tanks = new HashSet<>(); + @Store + protected boolean resizable; + + static FluidHandlerSimple simpleSingleTank() { + return new FluidHandlerSimple(false, new TankSimple(Fluid.BUCKET_VOLUME)); + } + + static FluidHandlerSimple simpleSingleTank(int capacity) { + return new FluidHandlerSimple(false, new TankSimple(capacity)); + } + + static FluidHandlerSimple simpleSingleTank(Predicate fluidFilter) { + return new FluidHandlerSimple(false, new TankSimple(Fluid.BUCKET_VOLUME).setFluidFilter(fluidFilter)); + } + + static FluidHandlerSimple simpleSingleTank(int capacity, Predicate fluidFilter) { + return new FluidHandlerSimple(false, new TankSimple(capacity).setFluidFilter(fluidFilter)); + } + + public FluidHandlerSimple() { + this.resizable = true; + } + + public FluidHandlerSimple(Tank... tanks) { + this(true, tanks); + } + + public FluidHandlerSimple(boolean resizable, Tank... tanks) { + this.tanks.addAll(Arrays.asList(tanks)); + this.resizable = resizable; + if (resizable) { + this.tanks.removeIf(Tank::isEmpty); + } + } + + @Override + public Set getTanks() { + return Collections.unmodifiableSet(tanks); + } + + @Override + public int addFluid(Fluid fluid, boolean simulate) { + if (fluid.amount() == 0) + return 0; + + Fluid f = fluid.clone(); + int added = 0; + + for (Tank tank : tanks) { + int a = tank.addFluid(f, simulate); + added += a; + f.remove(a); + if (f.amount() == 0) + break; + } + + if (f.amount() > 0 && resizable) { + Tank t = new TankSimple(); + added += t.addFluid(f); + tanks.add(t); + } + + return added; + } + + @Override + public Optional removeFluid(Fluid fluid, boolean simulate) { + if (fluid.amount() == 0) + return Optional.empty(); + + Fluid f = fluid.withAmount(0); + Fluid r = fluid.clone(); + + for (Tank tank : tanks) { + if (!tank.hasFluidType(fluid)) + continue; + + int removed = tank.removeFluid(r).get().amount(); + r.remove(removed); + f.add(removed); + + if (r.amount() == 0) + break; + } + + if (resizable) { + this.tanks.removeIf(Tank::isEmpty); + } + + return Optional.of(f).filter(fl -> fl.amount() > 0); + } + + @Override + public Optional removeFluid(int amount, boolean simulate) { + Optional fluid = tanks.stream() + .filter(Tank::hasFluid) + .findFirst() + .flatMap(Tank::getFluid) + .map(f -> f.withAmount(0)); + + if (amount == 0 || !fluid.isPresent()) + return fluid; + + Fluid f = fluid.get(); + + for (Tank tank : tanks) { + if (!tank.hasFluidType(f)) + continue; + + int removed = tank.removeFluid(amount).get().amount(); + amount -= removed; + f.add(removed); + + if (amount == 0) + break; + } + + if (resizable) { + this.tanks.removeIf(Tank::isEmpty); + } + + return Optional.of(f).filter(fl -> fl.amount() > 0); + } + + @Override + public void save(Data data) { + Storable.super.save(data); + data.put("tanks", tanks.stream() + .filter(t -> t instanceof Storable) + .collect(Collectors.toSet())); + } + + @Override + public void load(Data data) { + Storable.super.load(data); + tanks.removeIf(t -> t instanceof Storable); + tanks.addAll(data.getCollection("tanks")); + } +} diff --git a/src/main/java/nova/core/component/fluid/FluidHandlerWrapper.java b/src/main/java/nova/core/component/fluid/FluidHandlerWrapper.java new file mode 100644 index 000000000..e36987af0 --- /dev/null +++ b/src/main/java/nova/core/component/fluid/FluidHandlerWrapper.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA 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. + * + * NOVA 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 NOVA. If not, see . + */ +package nova.core.component.fluid; + +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * @author ExE Boss + */ +public class FluidHandlerWrapper extends FluidHandler { + + private final FluidHandler handler; + private final Predicate tankFilter; + + public FluidHandlerWrapper(FluidHandler handler, Predicate tankFilter) { + this.handler = handler; + this.tankFilter = tankFilter; + } + + @Override + public Optional removeFluid(Fluid fluid, boolean simulate) { + if (fluid.amount() == 0) + return Optional.empty(); + + Fluid f = fluid.withAmount(0); + Fluid r = fluid.clone(); + + for (Tank tank : getTanks()) { + if (!tank.hasFluidType(fluid)) + continue; + + int removed = tank.removeFluid(r).get().amount(); + r.remove(removed); + f.add(removed); + + if (r.amount() == 0) + break; + } + + return Optional.of(f).filter(fl -> fl.amount() > 0); + } + + @Override + public Optional removeFluid(int amount, boolean simulate) { + Optional fluid = getTanks().stream() + .filter(Tank::hasFluid) + .findFirst() + .flatMap(Tank::getFluid) + .map(f -> f.withAmount(0)); + + if (amount == 0 || !fluid.isPresent()) + return fluid; + + Fluid f = fluid.get(); + + for (Tank tank : getTanks()) { + if (!tank.hasFluidType(f)) + continue; + + int removed = tank.removeFluid(amount).get().amount(); + amount -= removed; + f.add(removed); + + if (amount == 0) + break; + } + + return Optional.of(f).filter(fl -> fl.amount() > 0); + } + + @Override + public int addFluid(Fluid fluid, boolean simulate) { + if (fluid.amount() == 0) + return 0; + + Fluid f = fluid.clone(); + int added = 0; + + for (Tank tank : getTanks()) { + int a = tank.addFluid(f, simulate); + added += a; + f.remove(a); + if (f.amount() == 0) + break; + } + + return added; + } + + @Override + public Set getTanks() { + return handler.getTanks().stream().filter(tankFilter).collect(Collectors.toSet()); + } +} diff --git a/src/main/java/nova/core/component/fluid/SidedTankProvider.java b/src/main/java/nova/core/component/fluid/FluidIO.java similarity index 64% rename from src/main/java/nova/core/component/fluid/SidedTankProvider.java rename to src/main/java/nova/core/component/fluid/FluidIO.java index 6ff35012d..5435135cf 100644 --- a/src/main/java/nova/core/component/fluid/SidedTankProvider.java +++ b/src/main/java/nova/core/component/fluid/FluidIO.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 NOVA, All rights reserved. + * Copyright (c) 2017 NOVA, All rights reserved. * This library is free software, licensed under GNU Lesser General Public License version 3 * * This file is part of NOVA. @@ -20,15 +20,26 @@ package nova.core.component.fluid; -import nova.core.util.Direction; - -import java.util.Set; - /** - * A block that provides a fluid container. - * @author Calclavia + * @author ExE Boss */ -//TODO: Implement Component. There will need to be a better way to handle direction. -public interface SidedTankProvider { - Set getTank(Direction dir); +public interface FluidIO extends FluidProvider, FluidConsumer { + + int getFluidAmount(); + + /** + * @return Whether this container is empty + */ + boolean isEmpty(); + + /** + * @return Whether this container is storing a fluid (is not empty) + */ + boolean hasFluid(); + + boolean hasFluidType(String id); + + boolean hasFluidType(Fluid fluid); + + boolean hasFluidType(FluidFactory fluid); } diff --git a/src/main/java/nova/core/component/fluid/FluidManager.java b/src/main/java/nova/core/component/fluid/FluidManager.java index 633084263..8b04969e3 100644 --- a/src/main/java/nova/core/component/fluid/FluidManager.java +++ b/src/main/java/nova/core/component/fluid/FluidManager.java @@ -22,6 +22,7 @@ import nova.core.util.registry.FactoryManager; import nova.core.util.registry.Registry; +import nova.internal.core.Game; import java.util.Optional; import java.util.function.Function; @@ -61,6 +62,12 @@ public FluidFactory register(FluidFactory factory) { @Override public void init() { - //TODO: Implement + Game.events().publish(new Init(this)); + } + + public class Init extends ManagerEvent { + public Init(FluidManager manager) { + super(manager); + } } } diff --git a/src/main/java/nova/core/component/fluid/FluidProvider.java b/src/main/java/nova/core/component/fluid/FluidProvider.java index 17cecdf0d..80974a4f8 100644 --- a/src/main/java/nova/core/component/fluid/FluidProvider.java +++ b/src/main/java/nova/core/component/fluid/FluidProvider.java @@ -27,6 +27,23 @@ * @see FluidConsumer */ public interface FluidProvider { + /** + * Attempt to extract fluid from this FluidProvider + * @param fluid The fluid type and max amount to extract + * @param simulate Whether to simulate the extraction + * @return Extracted {@link Fluid} + */ + Optional removeFluid(Fluid fluid, boolean simulate); + + /** + * Attempt to extract fluid from this FluidProvider + * @param fluid The fluid type and max amount to extract + * @return Extracted {@link Fluid} + */ + default Optional removeFluid(Fluid fluid) { + return removeFluid(fluid, false); + } + /** * Attempt to extract fluid from this FluidProvider * @param amount Amount of fluid to extract diff --git a/src/main/java/nova/core/component/fluid/Tank.java b/src/main/java/nova/core/component/fluid/Tank.java index 53ae78ebe..ce003fc43 100644 --- a/src/main/java/nova/core/component/fluid/Tank.java +++ b/src/main/java/nova/core/component/fluid/Tank.java @@ -21,35 +21,41 @@ package nova.core.component.fluid; import java.util.Optional; +import java.util.OptionalInt; /** * Classes with this interface declare ability to store fluids * @see FluidConsumer * @see Tank */ -public interface Tank extends FluidConsumer, FluidProvider { +public interface Tank extends FluidIO { /** * @return Maximum capacity of this container */ - int getFluidCapacity(); + OptionalInt getFluidCapacity(); /** * @return Fluid stored in this container */ Optional getFluid(); + @Override default int getFluidAmount() { return hasFluid() ? getFluid().get().amount() : 0; } - /** - * @return Whether this container is storing a fluid - */ + @Override + default boolean isEmpty() { + return !getFluid().isPresent(); + } + + @Override default boolean hasFluid() { return getFluid().isPresent(); } + @Override default boolean hasFluidType(String fluidID) { if (hasFluid()) { return getFluid().get().getID().equals(fluidID); @@ -58,6 +64,7 @@ default boolean hasFluidType(String fluidID) { return false; } + @Override default boolean hasFluidType(Fluid sample) { if (hasFluid()) { return getFluid().get().sameType(sample); @@ -66,6 +73,7 @@ default boolean hasFluidType(Fluid sample) { return false; } + @Override default boolean hasFluidType(FluidFactory sample) { if (hasFluid()) { return getFluid().get().sameType(sample); @@ -74,4 +82,7 @@ default boolean hasFluidType(FluidFactory sample) { return false; } + default Optional getTag() { + return Optional.empty(); + } } diff --git a/src/main/java/nova/core/component/fluid/TankProvider.java b/src/main/java/nova/core/component/fluid/TankProvider.java new file mode 100644 index 000000000..4613a920b --- /dev/null +++ b/src/main/java/nova/core/component/fluid/TankProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA 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. + * + * NOVA 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 NOVA. If not, see . + */ + +package nova.core.component.fluid; + +import java.util.Set; + +/** + * @author ExE Boss + */ +public interface TankProvider { + + Set getTanks(); +} diff --git a/src/main/java/nova/core/component/fluid/TankSimple.java b/src/main/java/nova/core/component/fluid/TankSimple.java index 6f3e6d6a3..450465711 100644 --- a/src/main/java/nova/core/component/fluid/TankSimple.java +++ b/src/main/java/nova/core/component/fluid/TankSimple.java @@ -24,8 +24,11 @@ import nova.core.network.Syncable; import nova.core.retention.Data; import nova.core.retention.Storable; +import nova.core.util.math.MathUtil; import java.util.Optional; +import java.util.OptionalInt; +import java.util.function.Predicate; /** * This class provides basic implementation of {@link Tank} @@ -33,25 +36,45 @@ public class TankSimple implements Tank, Storable, Syncable { private Optional containedFluid = Optional.empty(); - private int capacity; + private OptionalInt capacity; + private Predicate fluidFilter = f -> true; + private Optional name = Optional.empty(); public TankSimple() { - this(Fluid.bucketVolume); + this.capacity = OptionalInt.empty(); } public TankSimple(int maxCapacity) { - this.capacity = maxCapacity; + this.capacity = OptionalInt.of(maxCapacity); + } + + public TankSimple removeCapacity() { + this.capacity = OptionalInt.empty(); + return this; + } + + public TankSimple removeTag() { + this.name = Optional.empty(); + return this; } public TankSimple setCapacity(int capacity) { - this.capacity = capacity; + this.capacity = OptionalInt.of(capacity); setFluid(containedFluid); return this; } + public TankSimple setTag(String name) { + this.name = Optional.of(name); + return this; + } + @Override public int addFluid(Fluid fluid, boolean simulate) { - int capacity = this.capacity - containedFluid.orElse(fluid.withAmount(0)).amount(); + if (fluid.amount() == 0 || !fluidFilter.test(fluid)) + return 0; + + int capacity = this.capacity.orElse(Integer.MAX_VALUE) - containedFluid.orElseGet(() -> fluid.withAmount(0)).amount(); int toPut = Math.min(fluid.amount(), capacity); if (containedFluid.isPresent()) { @@ -72,6 +95,14 @@ public int addFluid(Fluid fluid, boolean simulate) { } } + @Override + public Optional removeFluid(Fluid fluid, boolean simulate) { + if (!containedFluid.filter(fluid::sameType).isPresent()) + return Optional.empty(); + + return removeFluid(fluid.amount(), simulate); + } + @Override public Optional removeFluid(int amount, boolean simulate) { if (!containedFluid.isPresent()) { @@ -97,7 +128,7 @@ public Optional removeFluid(int amount, boolean simulate) { } @Override - public int getFluidCapacity() { + public OptionalInt getFluidCapacity() { return capacity; } @@ -106,17 +137,21 @@ public Optional getFluid() { return containedFluid; } + public TankSimple setFluidFilter(Predicate fluidFilter) { + this.fluidFilter = fluidFilter; + return this; + } + public TankSimple setFluid(Optional fluid) { - this.containedFluid = fluid; - if (containedFluid.isPresent()) { - containedFluid.get().setAmount(Math.max(Math.min(containedFluid.get().amount(), capacity), 0)); - } + containedFluid = fluid.filter(fluidFilter).map(f -> f.withAmount(MathUtil.clamp(f.amount(), 0, capacity.orElse(Integer.MAX_VALUE)))).filter(f -> f.amount() > 0); return this; } @Override public void save(Data data) { - data.put("capacity", capacity); + if (capacity.isPresent()) { + data.put("capacity", capacity.getAsInt()); + } if (containedFluid.isPresent()) { data.put("fluid", containedFluid.get()); @@ -125,7 +160,11 @@ public void save(Data data) { @Override public void load(Data data) { - setCapacity(data.get("capacity")); + if (data.containsKey("capactiy")) { + setCapacity(data.get("capacity")); + } else { + removeCapacity(); + } if (data.containsKey("fluid")) { containedFluid = Optional.of(data.getStorable("fluid")); @@ -145,4 +184,9 @@ public void read(Packet packet) { public void write(Packet packet) { containedFluid = Optional.of((Fluid) packet.readStorable()); } + + @Override + public Optional getTag() { + return name; + } } diff --git a/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java b/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java index e92733430..b5c175ea2 100644 --- a/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java +++ b/src/test/java/nova/wrappertests/NovaLauncherTestFactory.java @@ -93,6 +93,7 @@ public NovaLauncher createLauncher(Class... modClasses) { Game.blocks().init(); Game.items().init(); Game.entities().init(); + Game.fluids().init(); Game.recipes().init(); return launcher;