mirror of
https://github.com/GTNewHorizons/EnderIO.git
synced 2026-11-15 09:34:50 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff0e85142d | ||
|
|
94bd521739 | ||
|
|
e66c50bc24 | ||
|
|
d9df657f35 | ||
|
|
08553f8af2 | ||
|
|
0fe564d007 | ||
|
|
53ba0383fb | ||
|
|
2c5664ce08 | ||
|
|
da70f52b0d | ||
|
|
46644bc889 | ||
|
|
f615df5010 |
No files matched your search
@@ -28,3 +28,4 @@ whitelist.json
|
||||
src/main/resources/mixins.*.json
|
||||
*.bat
|
||||
layout.json
|
||||
.DS_Store
|
||||
+18
-17
@@ -1,24 +1,25 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
api('com.github.GTNewHorizons:EnderCore:0.5.0:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:ForestryMC:4.10.17:dev')
|
||||
compileOnly('com.github.GTNewHorizons:NotEnoughItems:2.8.19-GTNH:dev')
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.7.0:dev")
|
||||
compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.45:dev')
|
||||
api('com.github.GTNewHorizons:EnderCore:0.5.5:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:ForestryMC:4.11.4:dev')
|
||||
compileOnly('com.github.GTNewHorizons:NotEnoughItems:2.8.60-GTNH:dev')
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.9.10:dev")
|
||||
compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.55:dev')
|
||||
api('curse.maven:cofh-lib-220333:2388748') // https://www.curseforge.com/minecraft/mc-mods/cofh-lib/files/2388748
|
||||
shadowImplementation('cglib:cglib-nodep:3.3.0')
|
||||
api("com.github.GTNewHorizons:TinkersConstruct:1.14.6-GTNH:dev")
|
||||
api("com.github.GTNewHorizons:TinkersConstruct:1.14.27-GTNH:dev")
|
||||
|
||||
compileOnly('com.github.GTNewHorizons:waila:1.9.2:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-717-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Baubles-Expanded:2.2.1-GTNH:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.60:dev') {transitive = false}
|
||||
compileOnly("com.github.GTNewHorizons:ModularUI2:2.3.4-1.7.10:dev") {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Railcraft:9.17.0:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:StorageDrawers:2.2.0-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Chisel:2.17.0-GTNH:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:OpenComputers:1.12.2-GTNH:api') {transitive = false}
|
||||
devOnlyNonPublishable('com.github.GTNewHorizons:waila:1.19.22:dev') {transitive = false}
|
||||
runtimeOnlyNonPublishable('com.github.GTNewHorizons:WAILAPlugins:0.7.2:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-812-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Baubles-Expanded:2.2.6-GTNH:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.261:dev') {transitive = false}
|
||||
compileOnly("com.github.GTNewHorizons:ModularUI2:2.3.37-1.7.10:dev") {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Railcraft:9.17.17:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:StorageDrawers:2.2.9-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Chisel:2.17.14-GTNH:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:OpenComputers:1.12.16-GTNH:api') {transitive = false}
|
||||
compileOnly('curse.maven:minefactory-reloaded-66672:2366150') // https://www.curseforge.com/minecraft/mc-mods/minefactory-reloaded/files/2366150
|
||||
compileOnly('thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev')
|
||||
compileOnly('curse.maven:ee3-65509:2305023') // https://www.curseforge.com/minecraft/mc-mods/ee3/files/2305023
|
||||
@@ -26,6 +27,6 @@ dependencies {
|
||||
compileOnly(rfg.deobf('curse.maven:mekanism-268560:2475797')) // https://www.curseforge.com/minecraft/mc-mods/mekanism/files/2475797
|
||||
compileOnly(rfg.deobf('maven.modrinth:immibis-microblocks:59.1.2')) // https://modrinth.com/mod/immibis-microblocks/version/59.1.2
|
||||
|
||||
compileOnlyApi('com.github.GTNewHorizons:Angelica:1.0.0-beta62:api') {transitive = false}
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.3:dev")
|
||||
compileOnlyApi('com.github.GTNewHorizons:Angelica:1.0.0-beta66a:api') {transitive = false}
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.58:dev")
|
||||
}
|
||||
+39
-4
@@ -39,9 +39,33 @@ remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/co
|
||||
# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE.
|
||||
developmentEnvironmentUserName = Developer
|
||||
|
||||
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
|
||||
# See https://github.com/bsideup/jabel for details on how this works.
|
||||
enableModernJavaSyntax = true
|
||||
# Enables modern Java syntax support. Valid values:
|
||||
# - false: No modern syntax, Java 8 only
|
||||
# - jabel: Jabel syntax-only support, compiles to J8 bytecode
|
||||
# - jvmDowngrader: Full modern Java via JVM Downgrader (syntax + stdlib APIs)
|
||||
# - modern: Native modern Java bytecode, no downgrading
|
||||
enableModernJavaSyntax = jabel
|
||||
|
||||
# If set, ignores the above setting and compiles with the given toolchain. This may cause unexpected issues,
|
||||
# and should *not* be used in most situations. -1 disables this.
|
||||
# forceToolchainVersion = -1
|
||||
|
||||
# Target JVM version for JVM Downgrader bytecode downgrading.
|
||||
# Only used when enableModernJavaSyntax = jvmDowngrader
|
||||
# downgradeTargetVersion = 8
|
||||
|
||||
# Comma-separated list of Java versions for multi-release jar support (JVM Downgrader only).
|
||||
# Classes will be available in META-INF/versions/N/ for each version N in this list.
|
||||
# Default: "21,25" (J25+ gets native classes, J21-24 gets partial downgrade, J8-20 gets full downgrade).
|
||||
# jvmDowngraderMultiReleaseVersions = 21,25
|
||||
|
||||
# Specifies how JVM Downgrader API stubs are provided. Options:
|
||||
# - shade: Shade minimized stubs into the jar
|
||||
# - gtnhlib: GTNHLib provides stubs at runtime (adds version constraint)
|
||||
# - external: Another dependency provides stubs (no constraint, no warning)
|
||||
# - (empty): Warning reminding you to configure stubs
|
||||
# Note: 'shade' option requires you to verify license compliance, see: https://github.com/unimined/JvmDowngrader/blob/main/LICENSE.md
|
||||
# jvmDowngraderStubsProvider =
|
||||
|
||||
# Enables injecting missing generics into the decompiled source code for a better coding experience.
|
||||
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
|
||||
@@ -96,7 +120,9 @@ usesMixinDebug = false
|
||||
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
|
||||
mixinPlugin =
|
||||
|
||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
||||
# Specify the package that contains all of your Mixins. The package must exist or
|
||||
# the build will fail. If you have a package property defined in your mixins.<modid>.json,
|
||||
# it must match with this or the build will fail.
|
||||
mixinsPackage =
|
||||
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
@@ -172,6 +198,12 @@ curseForgeRelations =
|
||||
# projects. New projects should not use this parameter.
|
||||
# customArchiveBaseName =
|
||||
|
||||
# Optional parameter to customize the default working directory used by the runClient* tasks. Relative to the project directory.
|
||||
# runClientWorkingDirectory = run/client
|
||||
|
||||
# Optional parameter to customize the default working directory used by the runServer* tasks. Relative to the project directory.
|
||||
# runServerWorkingDirectory = run/server
|
||||
|
||||
# Optional parameter to have the build automatically fail if an illegal version is used.
|
||||
# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'.
|
||||
# The check is ONLY performed if the version is a git tag.
|
||||
@@ -201,3 +233,6 @@ curseForgeRelations =
|
||||
# This is meant to be set in $HOME/.gradle/gradle.properties.
|
||||
# ideaCheckSpotlessOnBuild = true
|
||||
|
||||
# Non-GTNH properties
|
||||
org.gradle.configuration-cache = true
|
||||
org.gradle.parallel = true
|
||||
@@ -0,0 +1,12 @@
|
||||
#This file is generated by updateDaemonJvm
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/46949723aaa20c7b64d7ecfed7207034/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d6690dfd71c4c91e08577437b5b2beb0/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/3cd7045fca9a72cd9bc7d14a385e594c/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/552c7bffe0370c66410a51c55985b511/redirect
|
||||
toolchainVersion=25
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -114,7 +114,6 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -172,7 +171,6 @@ fi
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
@@ -212,8 +210,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+1
-2
@@ -70,11 +70,10 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.44'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.19'
|
||||
}
|
||||
|
||||
|
||||
@@ -214,6 +214,7 @@ public class EnderIO {
|
||||
public static final boolean hasLwjgl3 = Loader.isModLoaded("lwjgl3ify");
|
||||
public static final boolean hasGT5 = Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi");
|
||||
public static final boolean hasHP = Loader.isModLoaded("hodgepodge");
|
||||
public static final boolean hasWailaPlugins = Loader.isModLoaded("wailaplugins");
|
||||
|
||||
// Materials
|
||||
public static ItemCapacitor itemBasicCapacitor;
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -89,20 +89,20 @@ public abstract class AbstractEnderLiquidConduit extends AbstractLiquidConduit {
|
||||
|
||||
STELLAR(() -> Config.stellarEnderFluidConduitExtractRate, () -> Config.stellarEnderFluidConduitMaxIoRate);
|
||||
|
||||
private final Supplier<Integer> getMaxExtractPerTick;
|
||||
private final Supplier<Integer> getMaxIoPerTick;
|
||||
private final IntSupplier getMaxExtractPerTick;
|
||||
private final IntSupplier getMaxIoPerTick;
|
||||
|
||||
Type(Supplier<Integer> getMaxExtractPerTick, Supplier<Integer> getMaxIoPerTick) {
|
||||
Type(IntSupplier getMaxExtractPerTick, IntSupplier getMaxIoPerTick) {
|
||||
this.getMaxExtractPerTick = getMaxExtractPerTick;
|
||||
this.getMaxIoPerTick = getMaxIoPerTick;
|
||||
}
|
||||
|
||||
public int getMaxExtractPerTick() {
|
||||
return getMaxExtractPerTick.get();
|
||||
return getMaxExtractPerTick.getAsInt();
|
||||
}
|
||||
|
||||
public int getMaxIoPerTick() {
|
||||
return getMaxIoPerTick.get();
|
||||
return getMaxIoPerTick.getAsInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,11 +85,13 @@ public class EnderLiquidConduitNetwork extends AbstractConduitNetwork<ILiquidCon
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tank.externalTank.getTankInfo(conDir.getOpposite()) != null) {
|
||||
for (FluidTankInfo tankInfo : tank.externalTank.getTankInfo(conDir.getOpposite())) {
|
||||
FluidTankInfo[] tankInfos = tank.externalTank.getTankInfo(conDir.getOpposite());
|
||||
if (tankInfos != null) {
|
||||
for (FluidTankInfo tankInfo : tankInfos) {
|
||||
if (tankInfo == null || tankInfo.fluid == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FluidStack tryDrain = tankInfo.fluid.copy();
|
||||
tryDrain.amount = type.getMaxExtractPerTick();
|
||||
FluidStack drained = tank.externalTank.drain(conDir.getOpposite(), tryDrain, false);
|
||||
@@ -98,10 +100,12 @@ public class EnderLiquidConduitNetwork extends AbstractConduitNetwork<ILiquidCon
|
||||
|| !tryDrain.isFluidEqual(drained)) {
|
||||
continue;
|
||||
}
|
||||
int amountAccepted = fillFrom(tank, drained.copy(), true);
|
||||
|
||||
int amountAccepted = fillFrom(tank, drained, true);
|
||||
if (amountAccepted <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tryDrain.amount = amountAccepted;
|
||||
drained = tank.externalTank.drain(conDir.getOpposite(), tryDrain, true);
|
||||
if (drained == null || drained.amount <= 0) {
|
||||
@@ -115,7 +119,7 @@ public class EnderLiquidConduitNetwork extends AbstractConduitNetwork<ILiquidCon
|
||||
if (drained == null || drained.amount <= 0 || !matchedFilter(drained, con, conDir, true)) {
|
||||
return false;
|
||||
}
|
||||
int amountAccepted = fillFrom(tank, drained.copy(), true);
|
||||
int amountAccepted = fillFrom(tank, drained, true);
|
||||
if (amountAccepted <= 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -147,7 +151,6 @@ public class EnderLiquidConduitNetwork extends AbstractConduitNetwork<ILiquidCon
|
||||
resource = resource.copy();
|
||||
resource.amount = Math.min(resource.amount, type.getMaxIoPerTick());
|
||||
int filled = 0;
|
||||
int remaining = resource.amount;
|
||||
// TODO: Only change starting pos of iterator is doFill is true so a false then true returns the same
|
||||
|
||||
TankIterator iterator;
|
||||
@@ -158,13 +161,13 @@ public class EnderLiquidConduitNetwork extends AbstractConduitNetwork<ILiquidCon
|
||||
&& target.acceptsOuput
|
||||
&& target.isValid()
|
||||
&& matchedFilter(resource, target.con, target.conDir, false)) {
|
||||
int vol = target.externalTank.fill(target.tankDir, resource.copy(), doFill);
|
||||
remaining -= vol;
|
||||
// Use reused FluidStack instead of copying each iteration
|
||||
int vol = target.externalTank.fill(target.tankDir, resource, doFill);
|
||||
resource.amount -= vol;
|
||||
filled += vol;
|
||||
if (remaining <= 0) {
|
||||
if (resource.amount <= 0) {
|
||||
break;
|
||||
}
|
||||
resource.amount = remaining;
|
||||
}
|
||||
}
|
||||
if (!tank.con.isRoundRobin(tank.conDir)) iterator.rewind();
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package crazypants.enderio.machine.farm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemShears;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
@@ -31,7 +33,6 @@ import crazypants.enderio.ModObject;
|
||||
import crazypants.enderio.config.Config;
|
||||
import crazypants.enderio.machine.AbstractPoweredTaskEntity;
|
||||
import crazypants.enderio.machine.ContinuousTask;
|
||||
import crazypants.enderio.machine.IMachineRecipe.ResultStack;
|
||||
import crazypants.enderio.machine.IPoweredTask;
|
||||
import crazypants.enderio.machine.SlotDefinition;
|
||||
import crazypants.enderio.machine.farm.farmers.FarmersCommune;
|
||||
@@ -48,6 +49,8 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
private static final int TICKS_PER_WORK = 20;
|
||||
private boolean showingRange;
|
||||
|
||||
private final List<ItemStack> harvestBuffer = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return worldObj;
|
||||
@@ -424,6 +427,38 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
wasActive = isActive();
|
||||
worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord, zCoord);
|
||||
}
|
||||
tryMoveFromBuffer();
|
||||
}
|
||||
|
||||
private void tryMoveFromBuffer() {
|
||||
if (harvestBuffer.isEmpty() || worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<ItemStack> toRemove = new ArrayList<>();
|
||||
for (ItemStack stack : harvestBuffer) {
|
||||
if (stack == null || stack.stackSize <= 0) {
|
||||
toRemove.add(stack);
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemStack remaining = tryInsertToInputSlots(stack);
|
||||
if (remaining != null && remaining.stackSize > 0) {
|
||||
remaining = tryInsertToOutputSlots(remaining);
|
||||
}
|
||||
|
||||
if (remaining == null || remaining.stackSize == 0) {
|
||||
toRemove.add(stack);
|
||||
} else {
|
||||
stack.stackSize = remaining.stackSize;
|
||||
}
|
||||
}
|
||||
|
||||
harvestBuffer.removeAll(toRemove);
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -445,9 +480,18 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
setNotification("noPower");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isBufferNotEmpty() || isOutputFull()) {
|
||||
setNotification("outputFull");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isBufferNotEmpty() {
|
||||
return !harvestBuffer.isEmpty();
|
||||
}
|
||||
|
||||
protected void doTick() {
|
||||
|
||||
if (sendNotification && shouldDoWorkThisTick(TICKS_PER_WORK)) {
|
||||
@@ -488,7 +532,7 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
block = worldObj.getBlock(bc.x, bc.y, bc.z);
|
||||
}
|
||||
|
||||
if (isOutputFull()) {
|
||||
if (isOutputFull() || isBufferNotEmpty()) {
|
||||
setNotification("outputFull");
|
||||
return;
|
||||
}
|
||||
@@ -507,10 +551,8 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
new TargetPoint(worldObj.provider.dimensionId, bc.x, bc.y, bc.z, Config.farmParticlesMaxRange));
|
||||
for (EntityItem ei : harvest.getDrops()) {
|
||||
if (ei != null) {
|
||||
insertHarvestDrop(ei, bc);
|
||||
if (!ei.isDead) {
|
||||
worldObj.spawnEntityInWorld(ei);
|
||||
}
|
||||
addToBuffer(ei.getEntityItem().copy());
|
||||
ei.setDead();
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -552,6 +594,99 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
}
|
||||
}
|
||||
|
||||
private void addToBuffer(ItemStack stack) {
|
||||
if (stack == null || stack.stackSize <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ItemStack bufStack : harvestBuffer) {
|
||||
if (bufStack.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(bufStack, stack)) {
|
||||
int canAdd = bufStack.stackSize;
|
||||
if (canAdd > 0) {
|
||||
int addAmount = Math.min(canAdd, stack.stackSize);
|
||||
bufStack.stackSize += addAmount;
|
||||
stack.stackSize -= addAmount;
|
||||
|
||||
if (stack.stackSize <= 0) {
|
||||
markDirty();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
harvestBuffer.add(stack.copy());
|
||||
markDirty();
|
||||
}
|
||||
|
||||
private ItemStack tryInsertToInputSlots(ItemStack stack) {
|
||||
if (stack == null || stack.stackSize <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = minSupSlot; i <= maxSupSlot; i++) {
|
||||
if (stack.stackSize <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ItemStack slotStack = inventory[i];
|
||||
int stackLimit = getInventoryStackLimit(i);
|
||||
|
||||
if (isItemValidForSlot(i, stack)) {
|
||||
if (slotStack == null) {
|
||||
if (!isSlotLocked(i)) {
|
||||
int amount = Math.min(stack.stackSize, stackLimit);
|
||||
inventory[i] = stack.copy();
|
||||
inventory[i].stackSize = amount;
|
||||
stack.stackSize -= amount;
|
||||
markDirty();
|
||||
}
|
||||
} else if (slotStack.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(slotStack, stack)) {
|
||||
int canAdd = Math.min(stackLimit - slotStack.stackSize, stack.stackSize);
|
||||
if (canAdd > 0) {
|
||||
slotStack.stackSize += canAdd;
|
||||
stack.stackSize -= canAdd;
|
||||
markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stack.stackSize > 0 ? stack : null;
|
||||
}
|
||||
|
||||
private ItemStack tryInsertToOutputSlots(ItemStack stack) {
|
||||
if (stack == null || stack.stackSize <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = slotDefinition.minOutputSlot; i <= slotDefinition.maxOutputSlot; i++) {
|
||||
if (stack.stackSize <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ItemStack slotStack = inventory[i];
|
||||
int stackLimit = 64;
|
||||
|
||||
if (slotStack == null) {
|
||||
int amount = Math.min(stack.stackSize, stackLimit);
|
||||
inventory[i] = stack.copy();
|
||||
inventory[i].stackSize = amount;
|
||||
stack.stackSize -= amount;
|
||||
markDirty();
|
||||
} else if (slotStack.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(slotStack, stack)) {
|
||||
int canAdd = Math.min(stackLimit - slotStack.stackSize, stack.stackSize);
|
||||
if (canAdd > 0) {
|
||||
slotStack.stackSize += canAdd;
|
||||
stack.stackSize -= canAdd;
|
||||
markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stack.stackSize > 0 ? stack : null;
|
||||
}
|
||||
|
||||
private int bonemealCooldown = 5; // no need to persist this
|
||||
|
||||
private boolean hasBonemeal() {
|
||||
@@ -652,68 +787,6 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
return minSupSlot + 3;
|
||||
}
|
||||
|
||||
private void insertHarvestDrop(Entity entity, BlockCoord bc) {
|
||||
if (!worldObj.isRemote) {
|
||||
if (entity instanceof EntityItem && !entity.isDead) {
|
||||
EntityItem item = (EntityItem) entity;
|
||||
ItemStack stack = item.getEntityItem().copy();
|
||||
int numInserted = insertResult(stack, bc);
|
||||
stack.stackSize -= numInserted;
|
||||
item.setEntityItemStack(stack);
|
||||
if (stack.stackSize == 0) {
|
||||
item.setDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int insertResult(ItemStack stack, BlockCoord bc) {
|
||||
|
||||
int slot = bc != null ? getSupplySlotForCoord(bc) : minSupSlot;
|
||||
int[] slots = new int[NUM_SUPPLY_SLOTS];
|
||||
int k = 0;
|
||||
for (int j = slot; j <= maxSupSlot; j++) {
|
||||
slots[k++] = j;
|
||||
}
|
||||
for (int j = minSupSlot; j < slot; j++) {
|
||||
slots[k++] = j;
|
||||
}
|
||||
|
||||
int origSize = stack.stackSize;
|
||||
stack = stack.copy();
|
||||
|
||||
int inserted = 0;
|
||||
for (int j = 0; j < slots.length && inserted < stack.stackSize; j++) {
|
||||
int i = slots[j];
|
||||
ItemStack curStack = inventory[i];
|
||||
int inventoryStackLimit = getInventoryStackLimit(i);
|
||||
if (isItemValidForSlot(i, stack) && (curStack == null || curStack.stackSize < inventoryStackLimit)) {
|
||||
if (curStack == null) {
|
||||
if (stack.stackSize < inventoryStackLimit) {
|
||||
inventory[i] = stack.copy();
|
||||
inserted = stack.stackSize;
|
||||
} else {
|
||||
inventory[i] = stack.copy();
|
||||
inserted = inventoryStackLimit;
|
||||
inventory[i].stackSize = inserted;
|
||||
}
|
||||
} else if (curStack.isItemEqual(stack)) {
|
||||
inserted = Math.min(inventoryStackLimit - curStack.stackSize, stack.stackSize);
|
||||
inventory[i].stackSize += inserted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stack.stackSize -= inserted;
|
||||
if (inserted >= origSize) {
|
||||
return origSize;
|
||||
}
|
||||
|
||||
ResultStack[] in = new ResultStack[] { new ResultStack(stack) };
|
||||
mergeResults(in);
|
||||
return origSize - (in[0].item == null ? 0 : in[0].item.stackSize);
|
||||
}
|
||||
|
||||
private @Nonnull BlockCoord getNextCoord() {
|
||||
|
||||
int size = getFarmSize();
|
||||
@@ -752,11 +825,6 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
return EnderIO.blockFarmStation.getLocalizedName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInventoryName() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineName() {
|
||||
return ModObject.blockFarmStation.unlocalisedName;
|
||||
@@ -811,6 +879,17 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
} else if (slotLayoutVersion == 2) {
|
||||
inventory = (new ArrayMappingTool<ItemStack>("TTTSSSSOOOOOOC", "TTTBBSSSSOOOOOOC")).map(inventory);
|
||||
}
|
||||
|
||||
if (nbtRoot.hasKey("HarvestBuffer")) {
|
||||
NBTTagList bufferList = nbtRoot.getTagList("HarvestBuffer", 10);
|
||||
for (int i = 0; i < bufferList.tagCount(); i++) {
|
||||
NBTTagCompound itemTag = bufferList.getCompoundTagAt(i);
|
||||
ItemStack stack = ItemStack.loadItemStackFromNBT(itemTag);
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
harvestBuffer.add(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IPoweredTask createTask() {
|
||||
@@ -834,6 +913,18 @@ public class TileFarmStation extends AbstractPoweredTaskEntity implements IRange
|
||||
nbtRoot.setIntArray("lockedSlots", locked);
|
||||
}
|
||||
nbtRoot.setInteger("slotLayoutVersion", 3);
|
||||
|
||||
if (!harvestBuffer.isEmpty()) {
|
||||
NBTTagList bufferList = new NBTTagList();
|
||||
for (ItemStack stack : harvestBuffer) {
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
NBTTagCompound itemTag = new NBTTagCompound();
|
||||
stack.writeToNBT(itemTag);
|
||||
bufferList.appendTag(itemTag);
|
||||
}
|
||||
}
|
||||
nbtRoot.setTag("HarvestBuffer", bufferList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -159,10 +159,13 @@ public class BlockZombieGenerator extends AbstractMachineBlock<TileZombieGenerat
|
||||
|
||||
@Override
|
||||
public void getWailaInfo(List<String> tooltip, EntityPlayer player, World world, int x, int y, int z) {
|
||||
TileEntity te = world.getTileEntity(x, y, z);
|
||||
if (te != null && te instanceof TileZombieGenerator) {
|
||||
if (EnderIO.hasWailaPlugins) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (world.getTileEntity(x, y, z) instanceof TileZombieGenerator generator) {
|
||||
tooltip.add(
|
||||
((TileZombieGenerator) te).getFluidStored(ForgeDirection.UNKNOWN) + " "
|
||||
generator.getFluidStored(ForgeDirection.UNKNOWN) + " "
|
||||
+ EnderIO.lang.localize("fluid.millibucket.abr"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class TileReservoir extends TileEntityEio implements IFluidHandler, ITank
|
||||
}
|
||||
}
|
||||
|
||||
static final FluidStack WATER_BUCKET = FluidRegistry.getFluidStack("water", BUCKET_VOLUME);
|
||||
static final FluidStack WATER_BUCKET = new FluidStack(FluidRegistry.WATER, BUCKET_VOLUME);
|
||||
|
||||
BlockCoord[] multiblock = null;
|
||||
|
||||
@@ -156,7 +156,7 @@ public class TileReservoir extends TileEntityEio implements IFluidHandler, ITank
|
||||
if (tank.getFluid() == null) {
|
||||
return true;
|
||||
}
|
||||
if (fluid != null && fluid.getID() == tank.getFluid().getFluidID()) {
|
||||
if (fluid != null && fluid == tank.getFluid().getFluid()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -167,7 +167,7 @@ public class TileReservoir extends TileEntityEio implements IFluidHandler, ITank
|
||||
if (tank.getFluid() == null || fluid == null) {
|
||||
return false;
|
||||
}
|
||||
return tank.getFluid().getFluid().getID() == fluid.getID();
|
||||
return tank.getFluid().getFluid() == fluid;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -187,6 +187,10 @@ public class BlockTank extends AbstractMachineBlock<TileTank> implements IAdvanc
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void addBasicEntries(ItemStack itemstack, EntityPlayer entityplayer, List<String> list, boolean flag) {
|
||||
if (EnderIO.hasWailaPlugins) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemstack.stackTagCompound != null && itemstack.stackTagCompound.hasKey("tankContents")) {
|
||||
FluidStack fl = FluidStack
|
||||
.loadFluidStackFromNBT((NBTTagCompound) itemstack.stackTagCompound.getTag("tankContents"));
|
||||
@@ -219,9 +223,11 @@ public class BlockTank extends AbstractMachineBlock<TileTank> implements IAdvanc
|
||||
|
||||
@Override
|
||||
public void getWailaInfo(List<String> tooltip, EntityPlayer player, World world, int x, int y, int z) {
|
||||
TileEntity te = world.getTileEntity(x, y, z);
|
||||
if (te instanceof TileTank) {
|
||||
TileTank tank = (TileTank) te;
|
||||
if (EnderIO.hasWailaPlugins) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (world.getTileEntity(x, y, z) instanceof TileTank tank) {
|
||||
FluidStack stored = tank.tank.getFluid();
|
||||
String fluid = stored == null ? EnderIO.lang.localize("tooltip.none")
|
||||
: stored.getFluid().getLocalizedName(stored);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package crazypants.enderio.material;
|
||||
|
||||
import static net.minecraft.util.EnumChatFormatting.RESET;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.renderer.texture.IIconRegister;
|
||||
@@ -9,6 +12,7 @@ import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.util.MathHelper;
|
||||
|
||||
@@ -20,6 +24,7 @@ import cpw.mods.fml.relauncher.SideOnly;
|
||||
import crazypants.enderio.EnderIO;
|
||||
import crazypants.enderio.EnderIOTab;
|
||||
import crazypants.enderio.ModObject;
|
||||
import crazypants.enderio.config.Config;
|
||||
import crazypants.enderio.power.BasicCapacitor;
|
||||
import crazypants.enderio.power.Capacitors;
|
||||
import crazypants.enderio.power.ICapacitor;
|
||||
@@ -28,6 +33,7 @@ import crazypants.enderio.power.ICapacitorItem;
|
||||
public class ItemCapacitor extends Item implements ICapacitorItem {
|
||||
|
||||
private static final BasicCapacitor CAP = new BasicCapacitor();
|
||||
private static final String SPACE = " ";
|
||||
|
||||
public static ItemCapacitor create() {
|
||||
ItemCapacitor result = new ItemCapacitor();
|
||||
@@ -104,12 +110,43 @@ public class ItemCapacitor extends Item implements ICapacitorItem {
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List<String> par3List,
|
||||
boolean par4) {
|
||||
if (par1ItemStack != null && par1ItemStack.getItemDamage() > 0 && par1ItemStack.getItemDamage() != 7) {
|
||||
par3List.add(EnderIO.lang.localize("machine.tooltip.upgrade"));
|
||||
ICapacitor capacitor = getCapacitor(par1ItemStack);
|
||||
par3List.add(EnumChatFormatting.GREEN + EnderIO.lang.localize("machine.tooltip.upgrade.name"));
|
||||
if (SpecialTooltipHandler.showAdvancedTooltips()) {
|
||||
SpecialTooltipHandler.addDetailedTooltipFromResources(par3List, "enderio.machine.tooltip.upgrade");
|
||||
addUpgrades(par3List, capacitor);
|
||||
addRangeUpgrade(par3List, capacitor);
|
||||
} else {
|
||||
SpecialTooltipHandler.addShowDetailsTooltip(par3List);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addUpgrades(List<String> list, ICapacitor capacitor) {
|
||||
DecimalFormat formatter = new DecimalFormat("#,###");
|
||||
String tierString = EnumChatFormatting.AQUA + EnderIO.lang.localize("machine.tooltip.upgrade.tier");
|
||||
String maxEnergyStorageString = EnumChatFormatting.AQUA
|
||||
+ EnderIO.lang.localize("machine.tooltip.upgrade.energystorage");
|
||||
String maxEnergyReceivedString = EnumChatFormatting.AQUA
|
||||
+ EnderIO.lang.localize("machine.tooltip.upgrade.energyreceived");
|
||||
String maxEnergyExtractedString = EnumChatFormatting.AQUA
|
||||
+ EnderIO.lang.localize("machine.tooltip.upgrade.energyextracted");
|
||||
String upgrades = EnumChatFormatting.GOLD + EnderIO.lang.localize("machine.tooltip.upgrade");
|
||||
String maxEnergyStorage = formatter.format(capacitor.getMaxEnergyStored());
|
||||
int tier = capacitor.getTier();
|
||||
String maxEnergyReceived = formatter.format(capacitor.getMaxEnergyReceived());
|
||||
String maxEnergyExtracted = formatter.format(capacitor.getMaxEnergyExtracted());
|
||||
list.add(upgrades);
|
||||
list.add(SPACE + tierString + RESET + tier);
|
||||
list.add(SPACE + maxEnergyReceivedString + RESET + maxEnergyReceived);
|
||||
list.add(SPACE + maxEnergyExtractedString + RESET + maxEnergyExtracted);
|
||||
list.add(SPACE + maxEnergyStorageString + RESET + maxEnergyStorage);
|
||||
}
|
||||
|
||||
public void addRangeUpgrade(List<String> list, ICapacitor capacitor) {
|
||||
String farmStation = EnumChatFormatting.AQUA + EnderIO.lang.localize("machine.tooltip.upgrade.farmstation");
|
||||
String rangeUpgrade = EnumChatFormatting.GOLD + EnderIO.lang.localize("machine.tooltip.upgrade.range");
|
||||
int range = Config.farmBonusSize * capacitor.getTier() - 1 + 2;
|
||||
list.add(rangeUpgrade);
|
||||
list.add(SPACE + farmStation + RESET + range);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class SmartTank extends FluidTank {
|
||||
if (fl == null || fluid == null) {
|
||||
return false;
|
||||
}
|
||||
return fl.getID() == fluid.getFluidID();
|
||||
return fl == fluid.getFluid();
|
||||
}
|
||||
|
||||
public FluidStack drain(FluidStack resource, boolean doDrain) {
|
||||
@@ -67,7 +67,7 @@ public class SmartTank extends FluidTank {
|
||||
if (fluid != null) {
|
||||
return fluid.isFluidEqual(resource);
|
||||
} else if (restriction != null) {
|
||||
return resource.getFluid() != null && restriction.getID() == resource.getFluid().getID();
|
||||
return resource.getFluid() != null && restriction == resource.getFluid();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@@ -75,9 +75,9 @@ public class SmartTank extends FluidTank {
|
||||
|
||||
public boolean canFill(Fluid fl) {
|
||||
if (fluid != null) {
|
||||
return fluid.getFluid().getID() == fl.getID();
|
||||
return fluid.getFluid() == fl;
|
||||
} else if (restriction != null) {
|
||||
return restriction.getID() == fl.getID();
|
||||
return restriction == fl;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ public class WailaCompat implements IWailaDataProvider {
|
||||
PowerDisplayUtil.abrevation()));
|
||||
}
|
||||
|
||||
} else if (itemStack.getItem() == EnderIO.itemLiquidConduit) {
|
||||
} else if (itemStack.getItem() == EnderIO.itemLiquidConduit && !EnderIO.hasWailaPlugins) {
|
||||
NBTTagCompound nbtRoot = accessor.getNBTData();
|
||||
if (nbtRoot.hasKey("fluidLocked") && nbtRoot.hasKey("FluidName")) {
|
||||
boolean fluidTypeLocked = nbtRoot.getBoolean("fluidLocked");
|
||||
|
||||
@@ -373,9 +373,14 @@ enderio.endergeticCapacitor.name=Endergetic Capacitor
|
||||
enderio.endergisedCapacitor.name=Endergised Capacitor
|
||||
enderio.totemicCapacitor.name=Totemic Capacitor
|
||||
|
||||
enderio.machine.tooltip.upgrade=Machine Upgrade
|
||||
enderio.machine.tooltip.upgrade.tooltip.detailed.line1=Increases energy storage and
|
||||
enderio.machine.tooltip.upgrade.tooltip.detailed.line2=speed / range of machines
|
||||
enderio.machine.tooltip.upgrade.name=Machine Upgrade
|
||||
enderio.machine.tooltip.upgrade=Upgrades:
|
||||
enderio.machine.tooltip.upgrade.tier=Tier:
|
||||
enderio.machine.tooltip.upgrade.energyreceived=Max Energy Received:
|
||||
enderio.machine.tooltip.upgrade.energyextracted=Max Energy Extracted:
|
||||
enderio.machine.tooltip.upgrade.farmstation=Farming station radius:
|
||||
enderio.machine.tooltip.upgrade.energystorage=Max energy storage:
|
||||
enderio.machine.tooltip.upgrade.range=Range upgrade:
|
||||
enderio.machine.tooltip.clearConfig=This will clear all stored info!
|
||||
|
||||
#Machines
|
||||
|
||||
Reference in new issue
Block a user