mirror of
https://github.com/GTNewHorizons/EnderIO.git
synced 2026-11-15 01:25:13 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e12142890e | ||
|
|
e6ebb5dfec | ||
|
|
1d4f6831dd | ||
|
|
726ce46475 | ||
|
|
d01de95e8e | ||
|
|
b15d357f1a | ||
|
|
0fbf6f05ba | ||
|
|
bf9c2cd2c7 | ||
|
|
51b4c4e74c | ||
|
|
cf6b678dd9 | ||
|
|
6c205150b1 | ||
|
|
e39a1e1eb6 | ||
|
|
4a94c1ba90 | ||
|
|
0fc382dd13 | ||
|
|
04964e15e4 | ||
|
|
085ccc9d21 | ||
|
|
1903589e29 | ||
|
|
46971bbe0e | ||
|
|
4ccecf7bc0 | ||
|
|
92fb58f0c6 | ||
|
|
54c6db0afc | ||
|
|
84d9dcaf00 | ||
|
|
af923d1977 | ||
|
|
efb918fc6d | ||
|
|
6447ffb4d5 | ||
|
|
fb4c9bde59 | ||
|
|
bd47a39c83 | ||
|
|
43d74c9a7a | ||
|
|
6d3a631bb0 | ||
|
|
ccdef03296 | ||
|
|
56e163c234 |
No files matched your search
+12
-12
@@ -1,22 +1,22 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
api('com.github.GTNewHorizons:EnderCore:0.4.5:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:ForestryMC:4.8.4:dev')
|
||||
compileOnly('com.github.GTNewHorizons:NotEnoughItems:2.5.21-GTNH:dev')
|
||||
compileOnly("com.github.GTNewHorizons:GTNHLib:0.2.9:dev")
|
||||
api('com.github.GTNewHorizons:EnderCore:0.4.6:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:ForestryMC:4.9.16:dev')
|
||||
compileOnly('com.github.GTNewHorizons:NotEnoughItems:2.6.44-GTNH:dev')
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.5.20:dev")
|
||||
compileOnly('com.github.GTNewHorizons:BuildCraft:7.1.39: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')
|
||||
|
||||
compileOnly('com.github.GTNewHorizons:waila:1.7.1:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-328-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:waila:1.8.1:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-474-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Baubles:1.0.4:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.79:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Railcraft:9.15.5:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:StorageDrawers:1.13.3-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Chisel:2.14.1-GTNH:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:OpenComputers:1.10.6-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.67:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Railcraft:9.15.14:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:StorageDrawers:2.0.3-GTNH:api') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:Chisel:2.15.3-GTNH:dev') {transitive = false}
|
||||
compileOnly('com.github.GTNewHorizons:OpenComputers:1.10.27-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
|
||||
@@ -24,5 +24,5 @@ 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-alpha30:api') {transitive = false}
|
||||
compileOnlyApi('com.github.GTNewHorizons:Angelica:1.0.0-beta18:api') {transitive = false}
|
||||
}
|
||||
+12
-1
@@ -85,6 +85,11 @@ accessTransformersFile =
|
||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||
usesMixins = false
|
||||
|
||||
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
|
||||
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
|
||||
# Mixin classes will have access to "main" classes, but not the other way around.
|
||||
separateMixinSourceSet =
|
||||
|
||||
# Adds some debug arguments like verbose output and class export.
|
||||
usesMixinDebug = false
|
||||
|
||||
@@ -117,9 +122,15 @@ minimizeShadowedDependencies = true
|
||||
# If disabled, won't rename the shadowed classes.
|
||||
relocateShadowedDependencies = true
|
||||
|
||||
# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories.
|
||||
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
|
||||
includeWellKnownRepositories = true
|
||||
|
||||
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
|
||||
# list of strings, with the acceptable keys being(case does not matter):
|
||||
# cursemaven
|
||||
# modrinth
|
||||
excludeWellKnownRepositories =
|
||||
|
||||
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
|
||||
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
|
||||
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
|
||||
|
||||
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.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
Vendored
+2
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.14'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.29'
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import crazypants.enderio.conduit.BlockConduitBundle;
|
||||
import crazypants.enderio.conduit.IConduit;
|
||||
import crazypants.enderio.conduit.TileConduitBundle;
|
||||
import crazypants.enderio.conduit.facade.FacadeRenderer;
|
||||
import crazypants.enderio.conduit.gas.GasConduit;
|
||||
import crazypants.enderio.conduit.gas.GasUtil;
|
||||
@@ -378,7 +377,6 @@ public class ClientProxy extends CommonProxy {
|
||||
cbr = new ConduitBundleRenderer((float) Config.conduitScale);
|
||||
BlockConduitBundle.rendererId = RenderingRegistry.getNextAvailableRenderId();
|
||||
RenderingRegistry.registerBlockHandler(cbr);
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileConduitBundle.class, cbr);
|
||||
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileTravelAnchor.class, new TravelEntitySpecialRenderer());
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ import crazypants.util.EE3Util;
|
||||
modid = MODID,
|
||||
name = MOD_NAME,
|
||||
version = VERSION,
|
||||
dependencies = "required-after:CoFHLib@(1.0.3B3,);after:endercore;after:MineFactoryReloaded;after:Forestry;after:Waila@[1.5.8,);after:Thaumcraft;after:appliedenergistics2@[rv2-beta-8,);after:chisel",
|
||||
dependencies = "required-after:CoFHLib@(1.0.3B3,);after:endercore;after:MineFactoryReloaded;after:Forestry;after:Waila@[1.5.8,);after:Thaumcraft;after:appliedenergistics2@[rv2-beta-8,);after:chisel;required-after:gtnhlib@[0.2.10,)",
|
||||
guiFactory = "crazypants.enderio.config.ConfigFactoryEIO")
|
||||
public class EnderIO {
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ public abstract class AbstractItemConduit extends Item implements IConduitItem {
|
||||
if (MicroblocksUtil.supportMicroblocks() && tryAddToMicroblocks(stack, player, world, x, y, z, side)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BlockCoord placeAt = Util.canPlaceItem(stack, EnderIO.blockConduitBundle, player, world, x, y, z, side);
|
||||
if (placeAt != null) {
|
||||
if (!world.isRemote) {
|
||||
@@ -84,9 +83,7 @@ public abstract class AbstractItemConduit extends Item implements IConduitItem {
|
||||
stack.stackSize--;
|
||||
}
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
ForgeDirection dir = ForgeDirection.values()[side];
|
||||
int placeX = x + dir.offsetX;
|
||||
int placeY = y + dir.offsetY;
|
||||
@@ -116,7 +113,6 @@ public abstract class AbstractItemConduit extends Item implements IConduitItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -162,8 +158,7 @@ public abstract class AbstractItemConduit extends Item implements IConduitItem {
|
||||
System.out.println("AbstractItemConduit.onItemUse: Conduit null.");
|
||||
return false;
|
||||
}
|
||||
bundle.removeConduit(existingConduit);
|
||||
bundle.addConduit(newConduit);
|
||||
bundle.replaceConduit(existingConduit, newConduit);
|
||||
if (!player.capabilities.isCreativeMode) {
|
||||
stack.stackSize--;
|
||||
for (ItemStack drop : existingConduit.getDrops()) {
|
||||
|
||||
@@ -49,6 +49,8 @@ public interface IConduitBundle extends IInternalPowerHandler, IFluidHandler, II
|
||||
|
||||
void addConduit(IConduit conduit);
|
||||
|
||||
void replaceConduit(IConduit original, IConduit replacement);
|
||||
|
||||
void removeConduit(IConduit conduit);
|
||||
|
||||
Collection<IConduit> getConduits();
|
||||
|
||||
@@ -25,6 +25,7 @@ import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.FluidTankInfo;
|
||||
|
||||
import com.enderio.core.client.render.BoundingBox;
|
||||
import com.gtnewhorizon.gtnhlib.concurrent.cas.CasList;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.util.AECableType;
|
||||
@@ -66,7 +67,7 @@ public class TileConduitBundle extends TileEntityEio implements IConduitBundle {
|
||||
|
||||
public static final short NBT_VERSION = 1;
|
||||
|
||||
private final List<IConduit> conduits = new ArrayList<IConduit>();
|
||||
private final List<IConduit> conduits = new CasList<>();
|
||||
|
||||
private Block facadeId = null;
|
||||
private int facadeMeta = 0;
|
||||
@@ -74,9 +75,9 @@ public class TileConduitBundle extends TileEntityEio implements IConduitBundle {
|
||||
|
||||
private boolean facadeChanged;
|
||||
|
||||
private final List<CollidableComponent> cachedCollidables = new ArrayList<CollidableComponent>();
|
||||
private final List<CollidableComponent> cachedCollidables = new ArrayList<>();
|
||||
|
||||
private final List<CollidableComponent> cachedConnectors = new ArrayList<CollidableComponent>();
|
||||
private final List<CollidableComponent> cachedConnectors = new ArrayList<>();
|
||||
|
||||
private boolean conduitsDirty = true;
|
||||
private boolean collidablesDirty = true;
|
||||
@@ -404,6 +405,29 @@ public class TileConduitBundle extends TileEntityEio implements IConduitBundle {
|
||||
dirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceConduit(IConduit original, IConduit replacement) {
|
||||
if (worldObj.isRemote) {
|
||||
return;
|
||||
}
|
||||
// If you're wondering why I am not using conduit.writeToNBT, it is because there is some data that should not
|
||||
// persist, some of which causes crashes with energy conduits.
|
||||
NBTTagCompound[] originalData = new NBTTagCompound[ForgeDirection.values().length];
|
||||
for (ForgeDirection conduitConnection : original.getExternalConnections()) {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
original.writeConnectionSettingsToNBT(conduitConnection, tag);
|
||||
originalData[conduitConnection.ordinal()] = tag;
|
||||
}
|
||||
removeConduit(original);
|
||||
addConduit(replacement);
|
||||
for (int i = 0; i < originalData.length; i++) {
|
||||
NBTTagCompound nbt = originalData[i];
|
||||
if (nbt != null) {
|
||||
replacement.readConduitSettingsFromNBT(ForgeDirection.values()[i], nbt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConduit(IConduit conduit) {
|
||||
if (conduit != null) {
|
||||
@@ -513,7 +537,7 @@ public class TileConduitBundle extends TileEntityEio implements IConduitBundle {
|
||||
|
||||
@Override
|
||||
public List<CollidableComponent> getConnectors() {
|
||||
List<CollidableComponent> result = new ArrayList<CollidableComponent>();
|
||||
List<CollidableComponent> result = new ArrayList<>();
|
||||
addConnectors(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ public class LiquidConduit extends AbstractTankConduit {
|
||||
}
|
||||
}
|
||||
if (!foundFluid) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
FluidStack couldDrain = extTank.drain(dir.getOpposite(), MAX_EXTRACT_PER_TICK, false);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package crazypants.enderio.conduit.liquid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
@@ -56,10 +56,17 @@ public class LiquidConduitRenderer extends DefaultConduitRenderer implements IRe
|
||||
super.renderEntity(conduitBundleRenderer, te, conduit, x, y, z, partialTick, worldLight, rb);
|
||||
}
|
||||
|
||||
public void renderDynamicEntity(ConduitBundleRenderer conduitBundleRenderer, IConduitBundle te, IConduit conduit,
|
||||
double x, double y, double z, float partialTick, float worldLight) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderConduit(IIcon tex, IConduit conduit, CollidableComponent component, float brightness) {
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
if (isNSEWUD(component.dir)) {
|
||||
LiquidConduit lc = (LiquidConduit) conduit;
|
||||
IIcon fluidTex = conduit.getTransmitionTextureForState(component);
|
||||
FluidStack fluid = lc.getFluidType();
|
||||
if (fluid != null) {
|
||||
renderFluidOutline(component, fluid);
|
||||
@@ -67,33 +74,40 @@ public class LiquidConduitRenderer extends DefaultConduitRenderer implements IRe
|
||||
BoundingBox[] cubes = toCubes(component.bound);
|
||||
for (BoundingBox cube : cubes) {
|
||||
drawSection(cube, tex.getMinU(), tex.getMaxU(), tex.getMinV(), tex.getMaxV(), component.dir, false);
|
||||
// This check is kinda broken, but whatever, it was like that when this was done in a TESR too
|
||||
if (lc.getTank().getFilledRatio() <= 0) {
|
||||
continue;
|
||||
}
|
||||
tessellator.setColorOpaque_F(0.7f, 0.7f, 0.7f);
|
||||
drawSection(
|
||||
cube,
|
||||
fluidTex.getMinU(),
|
||||
fluidTex.getMaxU(),
|
||||
fluidTex.getMinV(),
|
||||
fluidTex.getMaxV(),
|
||||
component.dir,
|
||||
true);
|
||||
}
|
||||
|
||||
} else {
|
||||
drawSection(
|
||||
component.bound,
|
||||
tex.getMinU(),
|
||||
tex.getMaxU(),
|
||||
tex.getMinV(),
|
||||
tex.getMaxV(),
|
||||
component.dir,
|
||||
true);
|
||||
}
|
||||
|
||||
if (conduit.getConnectionMode(component.dir) == ConnectionMode.DISABLED) {
|
||||
final CubeRenderer cr = CubeRenderer.get();
|
||||
int i;
|
||||
tex = EnderIO.blockConduitBundle.getConnectorIcon(component.data);
|
||||
List<Vertex> corners = component.bound
|
||||
.getCornersWithUvForFace(component.dir, tex.getMinU(), tex.getMaxU(), tex.getMinV(), tex.getMaxV());
|
||||
for (i = corners.size() - 1; i >= 0; i--) {
|
||||
Vertex c = corners.get(i);
|
||||
cr.addVecWithUV(c.xyz, c.uv.x, c.uv.y);
|
||||
}
|
||||
// back face
|
||||
for (i = corners.size() - 1; i >= 0; i--) {
|
||||
Vertex c = corners.get(i);
|
||||
cr.addVecWithUV(c.xyz, c.uv.x, c.uv.y);
|
||||
if (conduit.getConnectionMode(component.dir) == ConnectionMode.DISABLED) {
|
||||
final CubeRenderer cr = CubeRenderer.get();
|
||||
int i;
|
||||
tex = EnderIO.blockConduitBundle.getConnectorIcon(component.data);
|
||||
List<Vertex> corners = component.bound.getCornersWithUvForFace(
|
||||
component.dir,
|
||||
tex.getMinU(),
|
||||
tex.getMaxU(),
|
||||
tex.getMinV(),
|
||||
tex.getMaxV());
|
||||
for (i = corners.size() - 1; i >= 0; i--) {
|
||||
Vertex c = corners.get(i);
|
||||
cr.addVecWithUV(c.xyz, c.uv.x, c.uv.y);
|
||||
}
|
||||
// back face
|
||||
for (i = corners.size() - 1; i >= 0; i--) {
|
||||
Vertex c = corners.get(i);
|
||||
cr.addVecWithUV(c.xyz, c.uv.x, c.uv.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,27 +127,29 @@ public class LiquidConduitRenderer extends DefaultConduitRenderer implements IRe
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<CollidableComponent, Map<Fluid, List<CachableRenderStatement>>> cache = new WeakHashMap<CollidableComponent, Map<Fluid, List<CachableRenderStatement>>>();
|
||||
private static final Map<CollidableComponent, Map<Fluid, List<CachableRenderStatement>>> cache = Collections
|
||||
.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
public static List<CachableRenderStatement> computeFluidOutlineToCache(CollidableComponent component, Fluid fluid,
|
||||
double scaleFactor, float outlineWidth) {
|
||||
|
||||
Map<Fluid, List<CachableRenderStatement>> cache0 = cache.get(component);
|
||||
if (cache0 == null) {
|
||||
cache0 = new HashMap<Fluid, List<CachableRenderStatement>>();
|
||||
cache.put(component, cache0);
|
||||
}
|
||||
// Only init once per component across all threads so the cache stays accurate.
|
||||
Map<Fluid, List<CachableRenderStatement>> cache0 = cache
|
||||
.computeIfAbsent(component, _k -> new ConcurrentHashMap<>());
|
||||
// The rest of this function 'should' be in a `computeIfAbsent` as well for:
|
||||
// `cache0.computeIfAbsent(fluid, _k -> ...)` but that won't cause a bug in this case,
|
||||
// just a bit more garbage.
|
||||
List<CachableRenderStatement> data = cache0.get(fluid);
|
||||
if (data != null) {
|
||||
return data;
|
||||
}
|
||||
data = new ArrayList<CachableRenderStatement>();
|
||||
cache0.put(fluid, data);
|
||||
data = new ArrayList<>();
|
||||
|
||||
IIcon texture = fluid.getStillIcon();
|
||||
if (texture == null) {
|
||||
texture = fluid.getIcon();
|
||||
if (texture == null) {
|
||||
cache0.put(fluid, data);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -192,6 +208,7 @@ public class LiquidConduitRenderer extends DefaultConduitRenderer implements IRe
|
||||
}
|
||||
}
|
||||
}
|
||||
cache0.put(fluid, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -239,49 +256,6 @@ public class LiquidConduitRenderer extends DefaultConduitRenderer implements IRe
|
||||
// done in the dynamic section
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDynamicEntity(ConduitBundleRenderer conduitBundleRenderer, IConduitBundle te, IConduit conduit,
|
||||
double x, double y, double z, float partialTick, float worldLight) {
|
||||
|
||||
if (((LiquidConduit) conduit).getTank().getFilledRatio() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<CollidableComponent> components = conduit.getCollidableComponents();
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
|
||||
calculateRatios((LiquidConduit) conduit);
|
||||
transmissionScaleFactor = conduit.getTransmitionGeometryScale();
|
||||
|
||||
IIcon tex;
|
||||
for (CollidableComponent component : components) {
|
||||
if (renderComponent(component)) {
|
||||
if (isNSEWUD(component.dir) && conduit.getTransmitionTextureForState(component) != null) {
|
||||
|
||||
tessellator.setColorOpaque_F(1, 1, 1);
|
||||
tex = conduit.getTransmitionTextureForState(component);
|
||||
|
||||
BoundingBox[] cubes = toCubes(component.bound);
|
||||
for (BoundingBox cube : cubes) {
|
||||
drawSection(
|
||||
cube,
|
||||
tex.getMinU(),
|
||||
tex.getMaxU(),
|
||||
tex.getMinV(),
|
||||
tex.getMaxV(),
|
||||
component.dir,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setVerticesForTransmission(BoundingBox bound, ForgeDirection id) {
|
||||
|
||||
|
||||
@@ -15,8 +15,7 @@ public class ItemMEConduit extends AbstractItemConduit {
|
||||
|
||||
private static ItemConduitSubtype[] subtypes = new ItemConduitSubtype[] {
|
||||
new ItemConduitSubtype(ModObject.itemMEConduit.name(), "enderio:itemMeConduit"),
|
||||
new ItemConduitSubtype(ModObject.itemMEConduit.name() + "Dense", "enderio:itemMeConduitDense"),
|
||||
new ItemConduitSubtype(ModObject.itemMEConduit.name() + "DenseUltra", "enderio:itemMeConduitDenseUltra") };
|
||||
new ItemConduitSubtype(ModObject.itemMEConduit.name() + "Dense", "enderio:itemMeConduitDense") };
|
||||
|
||||
public static ItemMEConduit create() {
|
||||
ItemMEConduit result = new ItemMEConduit();
|
||||
|
||||
@@ -11,7 +11,6 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityClientPlayerMP;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.IIcon;
|
||||
@@ -19,13 +18,9 @@ import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import com.enderio.core.client.render.BoundingBox;
|
||||
import com.enderio.core.client.render.CubeRenderer;
|
||||
import com.enderio.core.client.render.IconUtil;
|
||||
import com.enderio.core.client.render.RenderUtil;
|
||||
import com.enderio.core.common.util.BlockCoord;
|
||||
import com.enderio.core.common.util.IBlockAccessWrapper;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -53,59 +48,12 @@ import crazypants.util.RenderPassHelper;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@ThreadSafeISBRH(perThread = false)
|
||||
public class ConduitBundleRenderer extends TileEntitySpecialRenderer implements ISimpleBlockRenderingHandler {
|
||||
public class ConduitBundleRenderer implements ISimpleBlockRenderingHandler {
|
||||
|
||||
public ConduitBundleRenderer(float conduitScale) {}
|
||||
|
||||
public ConduitBundleRenderer() {}
|
||||
|
||||
@Override
|
||||
public void renderTileEntityAt(TileEntity te, double x, double y, double z, float partialTick) {
|
||||
IConduitBundle bundle = (IConduitBundle) te;
|
||||
EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer;
|
||||
if (bundle == null || (bundle.hasFacade() && bundle.getFacadeId().isOpaqueCube()
|
||||
&& !ConduitUtil.isFacadeHidden(bundle, player))) {
|
||||
return;
|
||||
}
|
||||
final Tessellator tessellator = Tessellator.instance;
|
||||
|
||||
float brightness = -1;
|
||||
for (IConduit con : bundle.getConduits()) {
|
||||
if (ConduitUtil.renderConduit(player, con)) {
|
||||
final ConduitRenderer renderer = con.getRenderer();
|
||||
if (renderer.isDynamic()) {
|
||||
if (brightness == -1) {
|
||||
BlockCoord loc = bundle.getLocation();
|
||||
brightness = bundle.getEntity().getWorldObj()
|
||||
.getLightBrightnessForSkyBlocks(loc.x, loc.y, loc.z, 0);
|
||||
|
||||
RenderUtil.bindBlockTexture();
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_LIGHTING_BIT);
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslated(x, y, z);
|
||||
|
||||
tessellator.startDrawingQuads();
|
||||
}
|
||||
renderer.renderDynamicEntity(this, bundle, con, x, y, z, partialTick, brightness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (brightness != -1) {
|
||||
tessellator.draw();
|
||||
|
||||
GL11.glShadeModel(GL11.GL_FLAT);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId,
|
||||
RenderBlocks rb) {
|
||||
|
||||
@@ -10,8 +10,4 @@ public interface ConduitRenderer {
|
||||
void renderEntity(ConduitBundleRenderer conduitBundleRenderer, IConduitBundle te, IConduit con, double x, double y,
|
||||
double z, float partialTick, float worldLight, RenderBlocks rb);
|
||||
|
||||
boolean isDynamic();
|
||||
|
||||
void renderDynamicEntity(ConduitBundleRenderer conduitBundleRenderer, IConduitBundle te, IConduit con, double x,
|
||||
double y, double z, float partialTick, float worldLight);
|
||||
}
|
||||
@@ -63,10 +63,6 @@ public class DefaultConduitRenderer implements ConduitRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderDynamicEntity(ConduitBundleRenderer conduitBundleRenderer, IConduitBundle te, IConduit con,
|
||||
double x, double y, double z, float partialTick, float worldLight) {}
|
||||
|
||||
protected void renderConduit(IIcon tex, IConduit conduit, CollidableComponent component, float brightness) {
|
||||
final CubeRenderer cr = CubeRenderer.get();
|
||||
|
||||
@@ -349,8 +345,4 @@ public class DefaultConduitRenderer implements ConduitRenderer {
|
||||
return new BoundingBox[] { bb };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamic() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,34 @@ public final class Config {
|
||||
*/
|
||||
public static int teleportStaffFailedBlinkDistance = 64;
|
||||
|
||||
/**
|
||||
* Sets the teleport staff right-click action.
|
||||
*
|
||||
* <p>
|
||||
* Values:
|
||||
* <ul>
|
||||
* <li><b>0:</b> Do nothing
|
||||
* <li><b>1:</b> Teleport to look
|
||||
* <li><b>2:</b> Teleport to anchor
|
||||
* <li><b>3:</b> Teleport to anchor, or to look if no anchor <em>(default)</em>
|
||||
* </ul>
|
||||
*/
|
||||
public static int teleportStaffAction = 3;
|
||||
|
||||
/**
|
||||
* Sets the teleport staff sneak right-click action.
|
||||
*
|
||||
* <p>
|
||||
* Values:
|
||||
* <ul>
|
||||
* <li><b>0:</b> Do nothing
|
||||
* <li><b>1:</b> Teleport to look <em>(default)</em>
|
||||
* <li><b>2:</b> Teleport to anchor
|
||||
* <li><b>3:</b> Teleport to anchor, or to look if no anchor
|
||||
* </ul>
|
||||
*/
|
||||
public static int teleportStaffSneakAction = 1;
|
||||
|
||||
public static int enderIoRange = 8;
|
||||
public static boolean enderIoMeAccessEnabled = true;
|
||||
|
||||
@@ -361,6 +389,8 @@ public final class Config {
|
||||
"TwilightForest:item.steeleafHoe", "TwilightForest:item.ironwoodHoe", "IC2:itemToolBronzeHoe" };
|
||||
public static List<ItemStack> farmHoes = new ArrayList<ItemStack>();
|
||||
public static int farmSaplingReserveAmount = 8;
|
||||
public static double farmParticlesMaxRange = 64;
|
||||
public static int farmParticlesCount = 15;
|
||||
|
||||
public static int magnetPowerUsePerSecondRF = 1;
|
||||
public static int magnetPowerCapacityRF = 100000;
|
||||
@@ -1269,6 +1299,27 @@ public final class Config {
|
||||
"Number of blocks teleported when no block is being looked at.")
|
||||
.getInt(teleportStaffFailedBlinkDistance);
|
||||
|
||||
teleportStaffAction = config.get(
|
||||
sectionStaff.name,
|
||||
"teleportStaffAction",
|
||||
teleportStaffAction,
|
||||
"Sets the action for right-click with the staff of teleportation. Values:\n" + " 0: Do nothing\n"
|
||||
+ " 1: Teleport to look\n"
|
||||
+ " 2: Teleport to anchor\n"
|
||||
+ " 3: Teleport to anchor, or look if no anchor (default)")
|
||||
.getInt(teleportStaffAction);
|
||||
|
||||
teleportStaffSneakAction = config.get(
|
||||
sectionStaff.name,
|
||||
"teleportStaffSneakAction",
|
||||
teleportStaffSneakAction,
|
||||
"Sets the action for sneak right-click with the staff of teleportation. Values:\n"
|
||||
+ " 0: Do nothing\n"
|
||||
+ " 1: Teleport to look (default)\n"
|
||||
+ " 2: Teleport to anchor\n"
|
||||
+ " 3: Teleport to anchor, or look if no anchor")
|
||||
.getInt(teleportStaffSneakAction);
|
||||
|
||||
enderIoRange = config.get(
|
||||
sectionEfficiency.name,
|
||||
"enderIoRange",
|
||||
@@ -2060,6 +2111,18 @@ public final class Config {
|
||||
+ "always shear all leaves.")
|
||||
.getInt(farmSaplingReserveAmount);
|
||||
|
||||
farmParticlesMaxRange = config.get(
|
||||
sectionFarm.name,
|
||||
"farmParticlesMaxRange",
|
||||
farmParticlesMaxRange,
|
||||
"The max range of the farm action particles.").getDouble(farmParticlesMaxRange);
|
||||
|
||||
farmParticlesCount = config.get(
|
||||
sectionFarm.name,
|
||||
"farmParticlesCount",
|
||||
farmParticlesCount,
|
||||
"The number of particles produces by farm action.").getInt(farmParticlesCount);
|
||||
|
||||
combustionGeneratorUseOpaqueModel = config
|
||||
.get(
|
||||
sectionAesthetic.name,
|
||||
|
||||
@@ -154,7 +154,8 @@ public class KeyTracker {
|
||||
if (player != null) {
|
||||
ItemStack travelItem = player.getHeldItem();
|
||||
if (travelItem == null || travelItem.getItem() == null
|
||||
|| !(travelItem.getItem() instanceof IItemOfTravel)) {
|
||||
|| !(travelItem.getItem() instanceof IItemOfTravel)
|
||||
|| !((IItemOfTravel) travelItem.getItem()).isActive(player, travelItem)) {
|
||||
travelItem = TravelController.instance.findTravelItemInInventoryOrBaubles(player);
|
||||
}
|
||||
|
||||
|
||||
@@ -386,7 +386,15 @@ public class ItemDarkSteelSword extends ItemSword
|
||||
|
||||
@Override
|
||||
public boolean isActive(EntityPlayer ep, ItemStack equipped) {
|
||||
return isTravelUpgradeActive(ep, equipped);
|
||||
if (ep != null && equipped != null && isTravelUpgradeActive(ep, equipped)) {
|
||||
// Only "active" if held while sneaking. But still "active" for the purposes of travel keybind if not held
|
||||
if (isEquipped(ep)) {
|
||||
return ep.isSneaking();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -400,12 +408,12 @@ public class ItemDarkSteelSword extends ItemSword
|
||||
}
|
||||
|
||||
private boolean isTravelUpgradeActive(EntityPlayer ep, ItemStack equipped) {
|
||||
return isEquipped(ep) && ep.isSneaking() && TravelUpgrade.loadFromItem(equipped) != null;
|
||||
return ep != null && equipped != null && TravelUpgrade.loadFromItem(equipped) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) {
|
||||
if (isTravelUpgradeActive(player, stack)) {
|
||||
if (isActive(player, stack)) {
|
||||
if (world.isRemote) {
|
||||
if (TravelController.instance.activateTravelAccessable(stack, world, player, TravelSource.STAFF)) {
|
||||
player.swingItem();
|
||||
|
||||
@@ -168,7 +168,8 @@ public abstract class AbstractMachineEntity extends TileEntityEio
|
||||
public final boolean isItemValidForSlot(int i, ItemStack itemstack) {
|
||||
if (slotDefinition.isUpgradeSlot(i)) {
|
||||
return itemstack != null && itemstack.getItem() == EnderIO.itemBasicCapacitor
|
||||
&& itemstack.getItemDamage() > 0;
|
||||
&& itemstack.getItemDamage() > 0
|
||||
&& itemstack.getItemDamage() != 7;
|
||||
}
|
||||
return isMachineItemValidForSlot(i, itemstack);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,12 @@ public class FarmingStationRenderer extends TechneMachineRenderer<TileFarmStatio
|
||||
bb = bb.translate(x, y, z);
|
||||
tessellator.setColorOpaque_F(1, 1, 1);
|
||||
tessellator.setBrightness(0xF000F0);
|
||||
CubeRenderer.get().render(bb, override != null ? override : Blocks.portal.getBlockTextureFromSide(1));
|
||||
IIcon ico = override != null ? override : Blocks.portal.getBlockTextureFromSide(1);
|
||||
float x1 = ico.getInterpolatedU(3);
|
||||
float x2 = ico.getInterpolatedU(13);
|
||||
float y1 = ico.getInterpolatedV(6);
|
||||
float y2 = ico.getInterpolatedV(10);
|
||||
CubeRenderer.get().render(bb, x1, x2, y1, y2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.enderio.core.common.util.BlockCoord;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import crazypants.enderio.config.Config;
|
||||
import crazypants.util.ClientUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
@@ -51,11 +52,7 @@ public class PacketFarmAction implements IMessage, IMessageHandler<PacketFarmAct
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(PacketFarmAction message, MessageContext ctx) {
|
||||
for (BlockCoord bc : message.coords) {
|
||||
for (int i = 0; i < 15; i++) {
|
||||
ClientUtil.spawnFarmParcticles(rand, bc);
|
||||
}
|
||||
}
|
||||
ClientUtil.spawnFarmParticles(rand, message.coords, Config.farmParticlesCount);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -458,8 +458,9 @@ public class TileFarmStation extends AbstractPoweredTaskEntity {
|
||||
IHarvestResult harvest = FarmersCommune.instance.harvestBlock(this, bc, block, meta);
|
||||
if (harvest != null && harvest.getDrops() != null) {
|
||||
PacketFarmAction pkt = new PacketFarmAction(harvest.getHarvestedBlocks());
|
||||
PacketHandler.INSTANCE
|
||||
.sendToAllAround(pkt, new TargetPoint(worldObj.provider.dimensionId, bc.x, bc.y, bc.z, 64));
|
||||
PacketHandler.INSTANCE.sendToAllAround(
|
||||
pkt,
|
||||
new TargetPoint(worldObj.provider.dimensionId, bc.x, bc.y, bc.z, Config.farmParticlesMaxRange));
|
||||
for (EntityItem ei : harvest.getDrops()) {
|
||||
if (ei != null) {
|
||||
insertHarvestDrop(ei, bc);
|
||||
@@ -487,7 +488,12 @@ public class TileFarmStation extends AbstractPoweredTaskEntity {
|
||||
inventory[minFirtSlot] = farmerJoe.inventory.mainInventory[0];
|
||||
PacketHandler.INSTANCE.sendToAllAround(
|
||||
new PacketFarmAction(bc),
|
||||
new TargetPoint(worldObj.provider.dimensionId, bc.x, bc.y, bc.z, 64));
|
||||
new TargetPoint(
|
||||
worldObj.provider.dimensionId,
|
||||
bc.x,
|
||||
bc.y,
|
||||
bc.z,
|
||||
Config.farmParticlesMaxRange));
|
||||
if (inventory[minFirtSlot] != null && inventory[minFirtSlot].stackSize == 0) {
|
||||
inventory[minFirtSlot] = null;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ public class TileZombieGenerator extends AbstractGeneratorEntity
|
||||
public String getMachineName() {
|
||||
return ModObject.blockFrankenzombieGenerator.unlocalisedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratorType getGeneratorType() {
|
||||
return GeneratorType.FRANKENZOMBIE;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TileEnderGenerator extends TileZombieGenerator {
|
||||
@@ -58,6 +63,11 @@ public class TileZombieGenerator extends AbstractGeneratorEntity
|
||||
protected Fluid getFluidType() {
|
||||
return EnderIO.fluidEnderDistillation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratorType getGeneratorType() {
|
||||
return GeneratorType.ENDER;
|
||||
}
|
||||
}
|
||||
|
||||
private static int IO_MB_TICK = 250;
|
||||
@@ -326,7 +336,7 @@ public class TileZombieGenerator extends AbstractGeneratorEntity
|
||||
}
|
||||
|
||||
public GeneratorType getGeneratorType() {
|
||||
return ((BlockZombieGenerator) worldObj.getBlock(xCoord, yCoord, zCoord)).getGeneratorType();
|
||||
return GeneratorType.ZOMBIE;
|
||||
}
|
||||
|
||||
public int getOutputPerTick() {
|
||||
|
||||
@@ -33,9 +33,10 @@ public enum Alloy {
|
||||
if (oreDictName != null) {
|
||||
this.oreIngots.add("ingot" + StringUtils.capitalize(oreDictName));
|
||||
this.oreBlocks.add("block" + StringUtils.capitalize(oreDictName));
|
||||
} else {
|
||||
this.oreIngots.add("ingot" + StringUtils.capitalize(baseName));
|
||||
this.oreBlocks.add("block" + StringUtils.capitalize(baseName));
|
||||
}
|
||||
this.oreIngots.add("ingot" + StringUtils.capitalize(baseName));
|
||||
this.oreBlocks.add("block" + StringUtils.capitalize(baseName));
|
||||
this.hardness = hardness;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public class ItemCapacitor extends Item implements ICapacitorItem {
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) {
|
||||
if (par1ItemStack != null && par1ItemStack.getItemDamage() > 0) {
|
||||
if (par1ItemStack != null && par1ItemStack.getItemDamage() > 0 && par1ItemStack.getItemDamage() != 7) {
|
||||
par3List.add(EnderIO.lang.localize("machine.tooltip.upgrade"));
|
||||
if (SpecialTooltipHandler.showAdvancedTooltips()) {
|
||||
SpecialTooltipHandler.addDetailedTooltipFromResources(par3List, "enderio.machine.tooltip.upgrade");
|
||||
|
||||
@@ -15,6 +15,7 @@ import cpw.mods.fml.relauncher.SideOnly;
|
||||
import crazypants.enderio.EnderIO;
|
||||
import crazypants.enderio.ModObject;
|
||||
import crazypants.enderio.api.teleport.TravelSource;
|
||||
import crazypants.enderio.config.Config;
|
||||
import crazypants.enderio.machine.power.PowerDisplayUtil;
|
||||
|
||||
public class ItemTeleportStaff extends ItemTravelStaff {
|
||||
@@ -56,14 +57,30 @@ public class ItemTeleportStaff extends ItemTravelStaff {
|
||||
@Override
|
||||
public ItemStack onItemRightClick(ItemStack equipped, World world, EntityPlayer player) {
|
||||
if (world.isRemote) {
|
||||
if (player.isSneaking()) {
|
||||
TravelController.instance
|
||||
.activateTravelAccessable(equipped, world, player, TravelSource.TELEPORT_STAFF);
|
||||
} else {
|
||||
TravelController.instance.doTeleport(player);
|
||||
int action = player.isSneaking() ? Config.teleportStaffSneakAction : Config.teleportStaffAction;
|
||||
switch (action) {
|
||||
case 0:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
case 1:
|
||||
TravelController.instance.doTeleport(player);
|
||||
player.swingItem();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
TravelController.instance
|
||||
.activateTravelAccessable(equipped, world, player, TravelSource.TELEPORT_STAFF);
|
||||
player.swingItem();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
TravelController.instance
|
||||
.activateTravelAccessable(equipped, world, player, TravelSource.TELEPORT_STAFF, true);
|
||||
player.swingItem();
|
||||
break;
|
||||
}
|
||||
}
|
||||
player.swingItem();
|
||||
return equipped;
|
||||
}
|
||||
|
||||
@@ -89,6 +106,12 @@ public class ItemTeleportStaff extends ItemTravelStaff {
|
||||
return power;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored(ItemStack item) {
|
||||
// Has infinite energy, always report as being full of energy for any validation-code purposes.
|
||||
return this.capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void getSubItems(Item item, CreativeTabs par2CreativeTabs, List par3List) {
|
||||
|
||||
@@ -3,10 +3,8 @@ package crazypants.enderio.teleport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -32,6 +30,7 @@ import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import com.enderio.core.common.util.BlockCoord;
|
||||
import com.enderio.core.common.util.Util;
|
||||
@@ -41,10 +40,12 @@ import com.enderio.core.common.vecmath.VecmathUtil;
|
||||
import com.enderio.core.common.vecmath.Vector2d;
|
||||
import com.enderio.core.common.vecmath.Vector3d;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import com.google.common.collect.RowSortedTable;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.TreeBasedTable;
|
||||
import com.gtnewhorizon.gtnhlib.GTNHLib;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
@@ -148,8 +149,9 @@ public class TravelController {
|
||||
// target must be a valid selectedCoord
|
||||
// selectedCoord can either be a block right above/below when the player is on anchor...
|
||||
if (on.x == x && on.z == z) return null;
|
||||
// or another anchor
|
||||
TileEntity maybeAnchor = target.getTileEntity(toTp.worldObj);
|
||||
// or another anchor. We need to look one block below because TP goes above the anchor.
|
||||
BlockCoord belowTarget = target.getLocation(ForgeDirection.DOWN);
|
||||
TileEntity maybeAnchor = belowTarget.getTileEntity(toTp.worldObj);
|
||||
if (!(maybeAnchor instanceof ITravelAccessable)) return "not anchor";
|
||||
ITravelAccessable anchor = (ITravelAccessable) maybeAnchor;
|
||||
if (!isValidTarget(toTp, target, TravelSource.BLOCK)) {
|
||||
@@ -160,7 +162,8 @@ public class TravelController {
|
||||
case STAFF_BLINK:
|
||||
if (Config.travelStaffKeybindEnabled) {
|
||||
if (equippedItem == null || equippedItem.getItem() == null
|
||||
|| !(equippedItem.getItem() instanceof IItemOfTravel)) {
|
||||
|| !(equippedItem.getItem() instanceof IItemOfTravel)
|
||||
|| !((IItemOfTravel) equippedItem.getItem()).isActive(toTp, equippedItem)) {
|
||||
equippedItem = findTravelItemInInventoryOrBaubles(toTp);
|
||||
}
|
||||
}
|
||||
@@ -190,12 +193,36 @@ public class TravelController {
|
||||
}
|
||||
|
||||
public boolean activateTravelAccessable(ItemStack equipped, World world, EntityPlayer player, TravelSource source) {
|
||||
return activateTravelAccessable(equipped, world, player, source, false);
|
||||
}
|
||||
|
||||
public boolean activateTravelAccessable(ItemStack equipped, World world, EntityPlayer player, TravelSource source,
|
||||
boolean alsoDoTeleport) {
|
||||
if (!hasTarget()) {
|
||||
if (alsoDoTeleport) {
|
||||
Optional<BlockCoord> destinationOptional = findTeleportDestination(player);
|
||||
if (destinationOptional.isPresent()) {
|
||||
BlockCoord destination = destinationOptional.get();
|
||||
PacketLongDistanceTravelEvent p = new PacketLongDistanceTravelEvent(
|
||||
player,
|
||||
false,
|
||||
source,
|
||||
true,
|
||||
destination.x,
|
||||
destination.y,
|
||||
destination.z);
|
||||
PacketHandler.INSTANCE.sendToServer(p);
|
||||
// We have no way of knowing if it will succeed, so just return false.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PacketLongDistanceTravelEvent p = new PacketLongDistanceTravelEvent(player, false, source);
|
||||
PacketHandler.INSTANCE.sendToServer(p);
|
||||
// We have no way of knowing if it will succeed, so just return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockCoord target = selectedCoord;
|
||||
TileEntity te = world.getTileEntity(target.x, target.y, target.z);
|
||||
if (te instanceof ITravelAccessable) {
|
||||
@@ -243,7 +270,10 @@ public class TravelController {
|
||||
sample.add(eye);
|
||||
// we test against our feets location
|
||||
sample.y -= playerHeight;
|
||||
if (doBlinkAround(player, source, sample, true)) {
|
||||
|
||||
Optional<BlockCoord> destinationOptional = findNearbyDestination(player, source, sample);
|
||||
if (destinationOptional.isPresent()
|
||||
&& travelToLocation(player, source, destinationOptional.get(), true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -280,7 +310,9 @@ public class TravelController {
|
||||
// we test against our feets location
|
||||
sample.y -= playerHeight;
|
||||
|
||||
if (doBlinkAround(player, source, sample, false)) {
|
||||
Optional<BlockCoord> destinationOptional = findNearbyDestination(player, source, sample);
|
||||
if (destinationOptional.isPresent()
|
||||
&& travelToLocation(player, source, destinationOptional.get(), false)) {
|
||||
return true;
|
||||
}
|
||||
teleDistance++;
|
||||
@@ -296,7 +328,9 @@ public class TravelController {
|
||||
// we test against our feets location
|
||||
sample.y -= playerHeight;
|
||||
|
||||
if (doBlinkAround(player, source, sample, false)) {
|
||||
Optional<BlockCoord> destinationOptional = findNearbyDestination(player, source, sample);
|
||||
if (destinationOptional.isPresent()
|
||||
&& travelToLocation(player, source, destinationOptional.get(), false)) {
|
||||
return true;
|
||||
}
|
||||
sampleDistance--;
|
||||
@@ -308,114 +342,13 @@ public class TravelController {
|
||||
|
||||
/** This is the teleport staff super-teleport. */
|
||||
public boolean doTeleport(EntityPlayer player) {
|
||||
TravelSource source = TravelSource.TELEPORT_STAFF_BLINK;
|
||||
|
||||
Vector3d eye = Util.getEyePositionEio(player);
|
||||
Vector3d look = Util.getLookVecEio(player);
|
||||
|
||||
double playerHeight = player.yOffset;
|
||||
// +2 to compensate for the standard distance decrement of -2
|
||||
double teleDistance = Config.teleportStaffFailedBlinkDistance + 2;
|
||||
Vec3 eye3 = Vec3.createVectorHelper(eye.x, eye.y, eye.z);
|
||||
|
||||
// rayTraceBlocks has a limit of 200 distance.
|
||||
double maxDistance = Config.teleportStaffMaxBlinkDistance;
|
||||
double currDistance = 0;
|
||||
Vec3 pos = eye3;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
double distance = 200;
|
||||
if (maxDistance - currDistance < 200) {
|
||||
distance = maxDistance - currDistance;
|
||||
loop = false;
|
||||
}
|
||||
|
||||
Vector3d sample = new Vector3d(look);
|
||||
sample.scale(distance);
|
||||
sample.add(eye);
|
||||
Vec3 end = Vec3.createVectorHelper(sample.x, sample.y, sample.z);
|
||||
|
||||
MovingObjectPosition p = player.worldObj
|
||||
.rayTraceBlocks(pos, end, !Config.travelStaffBlinkThroughClearBlocksEnabled);
|
||||
if (p != null) {
|
||||
teleDistance = VecmathUtil.distance(eye, new Vector3d(p.blockX + 0.5, p.blockY + 0.5, p.blockZ + 0.5));
|
||||
break;
|
||||
}
|
||||
|
||||
pos = end;
|
||||
currDistance += distance;
|
||||
}
|
||||
|
||||
Vector3d sample = new Vector3d(look);
|
||||
sample.scale(Config.teleportStaffMaxBlinkDistance);
|
||||
sample.add(eye);
|
||||
Vec3 end = Vec3.createVectorHelper(sample.x, sample.y, sample.z);
|
||||
MovingObjectPosition p = player.worldObj
|
||||
.rayTraceBlocks(eye3, end, !Config.travelStaffBlinkThroughClearBlocksEnabled);
|
||||
if (p != null) {
|
||||
teleDistance = VecmathUtil.distance(eye, new Vector3d(p.blockX + 0.5, p.blockY + 0.5, p.blockZ + 0.5));
|
||||
}
|
||||
|
||||
double distanceIncrement = -2;
|
||||
// Special case: if the targeted block is too close, we'll try to teleport through it.
|
||||
if (teleDistance < 3) {
|
||||
distanceIncrement = 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
teleDistance += distanceIncrement;
|
||||
|
||||
sample.set(look);
|
||||
sample.scale(teleDistance);
|
||||
sample.add(eye);
|
||||
// we test against our feets location
|
||||
sample.y -= playerHeight;
|
||||
|
||||
if (doBlinkAround(player, source, sample, false)) {
|
||||
return true;
|
||||
}
|
||||
Optional<BlockCoord> destinationOptional = findTeleportDestination(player);
|
||||
if (destinationOptional.isPresent()) {
|
||||
return travelToLocation(player, TravelSource.TELEPORT_STAFF_BLINK, destinationOptional.get(), false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns empty optional if no travel destination was found. */
|
||||
public Optional<BlockCoord> findTravelDestination(EntityPlayer player, TravelSource source) {
|
||||
Vector3d eye = Util.getEyePositionEio(player);
|
||||
Vector3d look = Util.getLookVecEio(player);
|
||||
|
||||
// Map of distance to coordinate for eligible travel destinations (within angle).
|
||||
Map<Double, BlockCoord> distanceMap = new TreeMap<>();
|
||||
// Limit the max distance at which we'll display an out of range message.
|
||||
// Otherwise, you could trigger the message for any travel anchor on the entire server.
|
||||
double maxMessageDistance = 1.25 * source.getMaxDistanceTravelled();
|
||||
boolean displayOutOfRangeMessage = false;
|
||||
for (BlockCoord p : travelDestinations.get(player.worldObj.provider.dimensionId)) {
|
||||
Vector3d block = new Vector3d(p.x + 0.5, p.y + 0.5, p.z + 0.5);
|
||||
block.sub(eye);
|
||||
double distance = block.length();
|
||||
if (distance > maxMessageDistance) {
|
||||
continue;
|
||||
}
|
||||
block.normalize();
|
||||
|
||||
double angle = Math.acos(look.dot(block));
|
||||
// Roughly 5 degrees
|
||||
if (angle < 0.087) {
|
||||
if (distance > source.getMaxDistanceTravelled()) {
|
||||
displayOutOfRangeMessage = true;
|
||||
} else {
|
||||
distanceMap.put(distance, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (displayOutOfRangeMessage && distanceMap.isEmpty()) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.blockTravelPlatform.outOfRange"));
|
||||
}
|
||||
|
||||
return distanceMap.values().stream().findFirst();
|
||||
}
|
||||
|
||||
private boolean isBlackListedBlock(EntityPlayer player, MovingObjectPosition pos, Block hitBlock) {
|
||||
UniqueIdentifier ui = GameRegistry.findUniqueIdentifierFor(hitBlock);
|
||||
if (ui == null) {
|
||||
@@ -426,36 +359,6 @@ public class TravelController {
|
||||
|| !Config.travelStaffBlinkThroughUnbreakableBlocksEnabled);
|
||||
}
|
||||
|
||||
private boolean doBlinkAround(EntityPlayer player, TravelSource source, Vector3d sample, boolean conserveMomentum) {
|
||||
if (travelToLocation(
|
||||
player,
|
||||
source,
|
||||
new BlockCoord((int) Math.floor(sample.x), (int) Math.floor(sample.y), (int) Math.floor(sample.z)),
|
||||
conserveMomentum)) {
|
||||
return true;
|
||||
}
|
||||
if (travelToLocation(
|
||||
player,
|
||||
source,
|
||||
new BlockCoord((int) Math.floor(sample.x), (int) Math.floor(sample.y) + 1, (int) Math.floor(sample.z)),
|
||||
conserveMomentum)) {
|
||||
return true;
|
||||
}
|
||||
if (!Config.travelStaffSearchOptimize) {
|
||||
if (travelToLocation(
|
||||
player,
|
||||
source,
|
||||
new BlockCoord(
|
||||
(int) Math.floor(sample.x),
|
||||
(int) Math.floor(sample.y) - 1,
|
||||
(int) Math.floor(sample.z)),
|
||||
conserveMomentum)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean showTargets() {
|
||||
return showTargets && selectionEnabled;
|
||||
}
|
||||
@@ -492,6 +395,13 @@ public class TravelController {
|
||||
.getBlock(selectedCoord.x, selectedCoord.y, selectedCoord.z) == EnderIO.blockEnderIo;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldLoad(WorldEvent.Load e) {
|
||||
if (!e.world.isRemote) {
|
||||
travelDestinations.removeAll(e.world.provider.dimensionId);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void onRender(RenderWorldLastEvent event) {
|
||||
@@ -527,7 +437,7 @@ public class TravelController {
|
||||
}
|
||||
onBlockCoord = getActiveTravelBlock(player);
|
||||
boolean onBlock = onBlockCoord != null;
|
||||
showTargets = onBlock || isTravelItemActive(player, false);
|
||||
showTargets = onBlock || (isTravelItemActive(player, false) && !shouldHideTargets(player));
|
||||
if (showTargets) {
|
||||
updateSelectedTarget(player);
|
||||
} else {
|
||||
@@ -619,6 +529,16 @@ public class TravelController {
|
||||
return getTravelItemTravelSource(ep, checkInventoryAndBaubles) != null;
|
||||
}
|
||||
|
||||
/** Currently, we only hide travel targets for the teleport staff, in certain action modes. */
|
||||
public boolean shouldHideTargets(EntityPlayer ep) {
|
||||
if (getTravelItemTravelSource(ep, false) != TravelSource.TELEPORT_STAFF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int action = ep.isSneaking() ? Config.teleportStaffSneakAction : Config.teleportStaffAction;
|
||||
return action < 2;
|
||||
}
|
||||
|
||||
/** Returns null if no travel item is in inventory/baubles. */
|
||||
@Nullable
|
||||
public TravelSource getTravelItemTravelSource(EntityPlayer ep, boolean checkInventoryAndBaubles) {
|
||||
@@ -628,7 +548,8 @@ public class TravelController {
|
||||
|
||||
ItemStack equipped = ep.getCurrentEquippedItem();
|
||||
if (checkInventoryAndBaubles) {
|
||||
if (equipped == null || !(equipped.getItem() instanceof IItemOfTravel)) {
|
||||
if (equipped == null || !(equipped.getItem() instanceof IItemOfTravel)
|
||||
|| !((IItemOfTravel) equipped.getItem()).isActive(ep, equipped)) {
|
||||
equipped = findTravelItemInInventoryOrBaubles(ep);
|
||||
}
|
||||
}
|
||||
@@ -657,7 +578,8 @@ public class TravelController {
|
||||
ItemStack travelItem = null;
|
||||
for (int i = 0; i < ep.inventory.getSizeInventory(); i++) {
|
||||
ItemStack stack = ep.inventory.getStackInSlot(i);
|
||||
if (stack != null && stack.getItem() instanceof IItemOfTravel) {
|
||||
if (stack != null && stack.getItem() instanceof IItemOfTravel
|
||||
&& ((IItemOfTravel) stack.getItem()).isActive(ep, stack)) {
|
||||
travelItem = stack;
|
||||
break;
|
||||
}
|
||||
@@ -668,7 +590,8 @@ public class TravelController {
|
||||
if (baubles != null) {
|
||||
for (int i = 0; i < baubles.getSizeInventory(); i++) {
|
||||
ItemStack stack = baubles.getStackInSlot(i);
|
||||
if (stack != null && stack.getItem() instanceof IItemOfTravel) {
|
||||
if (stack != null && stack.getItem() instanceof IItemOfTravel
|
||||
&& ((IItemOfTravel) stack.getItem()).isActive(ep, stack)) {
|
||||
travelItem = stack;
|
||||
break;
|
||||
}
|
||||
@@ -692,7 +615,8 @@ public class TravelController {
|
||||
int travelItemSlot = -1;
|
||||
for (int i = 0; i < ep.inventory.getSizeInventory(); i++) {
|
||||
ItemStack stack = ep.inventory.getStackInSlot(i);
|
||||
if (stack != null && (stack.getItem() instanceof IItemOfTravel)) {
|
||||
if (stack != null && stack.getItem() instanceof IItemOfTravel
|
||||
&& ((IItemOfTravel) stack.getItem()).isActive(ep, stack)) {
|
||||
travelItemSlot = i;
|
||||
break;
|
||||
}
|
||||
@@ -703,7 +627,8 @@ public class TravelController {
|
||||
if (baubles != null) {
|
||||
for (int i = 0; i < baubles.getSizeInventory(); i++) {
|
||||
ItemStack stack = baubles.getStackInSlot(i);
|
||||
if (stack != null && stack.getItem() instanceof IItemOfTravel) {
|
||||
if (stack != null && stack.getItem() instanceof IItemOfTravel
|
||||
&& ((IItemOfTravel) stack.getItem()).isActive(ep, stack)) {
|
||||
travelItemSlot = -(i + 2);
|
||||
break;
|
||||
}
|
||||
@@ -713,43 +638,201 @@ public class TravelController {
|
||||
return travelItemSlot;
|
||||
}
|
||||
|
||||
/** Finds the destination for the teleport staff super-teleport, or returns empty optional if unsuccessful. */
|
||||
public Optional<BlockCoord> findTeleportDestination(EntityPlayer player) {
|
||||
TravelSource source = TravelSource.TELEPORT_STAFF_BLINK;
|
||||
|
||||
Vector3d eye = Util.getEyePositionEio(player);
|
||||
Vector3d look = Util.getLookVecEio(player);
|
||||
|
||||
double playerHeight = player.yOffset;
|
||||
// +2 to compensate for the standard distance decrement of -2
|
||||
double teleDistance = Config.teleportStaffFailedBlinkDistance + 2;
|
||||
Vec3 eye3 = Vec3.createVectorHelper(eye.x, eye.y, eye.z);
|
||||
|
||||
// rayTraceBlocks has a limit of 200 distance.
|
||||
double maxDistance = Config.teleportStaffMaxBlinkDistance;
|
||||
double currDistance = 0;
|
||||
Vec3 pos = eye3;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
double distance = 200;
|
||||
if (maxDistance - currDistance < 200) {
|
||||
distance = maxDistance - currDistance;
|
||||
loop = false;
|
||||
}
|
||||
|
||||
Vector3d sample = new Vector3d(look);
|
||||
sample.scale(distance);
|
||||
sample.add(eye);
|
||||
Vec3 end = Vec3.createVectorHelper(sample.x, sample.y, sample.z);
|
||||
|
||||
MovingObjectPosition p = player.worldObj
|
||||
.rayTraceBlocks(pos, end, !Config.travelStaffBlinkThroughClearBlocksEnabled);
|
||||
if (p != null) {
|
||||
teleDistance = VecmathUtil.distance(eye, new Vector3d(p.blockX + 0.5, p.blockY + 0.5, p.blockZ + 0.5));
|
||||
break;
|
||||
}
|
||||
|
||||
pos = end;
|
||||
currDistance += distance;
|
||||
}
|
||||
|
||||
Vector3d sample = new Vector3d(look);
|
||||
sample.scale(Config.teleportStaffMaxBlinkDistance);
|
||||
sample.add(eye);
|
||||
Vec3 end = Vec3.createVectorHelper(sample.x, sample.y, sample.z);
|
||||
MovingObjectPosition p = player.worldObj
|
||||
.rayTraceBlocks(eye3, end, !Config.travelStaffBlinkThroughClearBlocksEnabled);
|
||||
if (p != null) {
|
||||
teleDistance = VecmathUtil.distance(eye, new Vector3d(p.blockX + 0.5, p.blockY + 0.5, p.blockZ + 0.5));
|
||||
}
|
||||
|
||||
double distanceIncrement = -2;
|
||||
int maxIter = Math.min(8, (int) teleDistance / 2);
|
||||
// Special case: if the targeted block is too close, we'll try to teleport through it.
|
||||
if (teleDistance < 4) {
|
||||
distanceIncrement = 0.5;
|
||||
maxIter = 32;
|
||||
}
|
||||
|
||||
for (int i = 0; i < maxIter; i++) {
|
||||
teleDistance += distanceIncrement;
|
||||
|
||||
sample.set(look);
|
||||
sample.scale(teleDistance);
|
||||
sample.add(eye);
|
||||
// we test against our feets location
|
||||
sample.y -= playerHeight;
|
||||
|
||||
Optional<BlockCoord> destinationOptional = findNearbyDestination(player, source, sample);
|
||||
if (destinationOptional.isPresent()) {
|
||||
return destinationOptional;
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/** Finds a long-distance travel anchor, or returns empty optional if unsuccessful. */
|
||||
public Optional<BlockCoord> findTravelDestination(EntityPlayer player, TravelSource source) {
|
||||
double maxDistance = source.getMaxDistanceTravelled();
|
||||
double maxMessageDistance = 1.25 * maxDistance;
|
||||
// Find possible destinations within about 5 degrees.
|
||||
RowSortedTable<Double, Double, BlockCoord> possibleDestinations = findBlocksWithinAngle(
|
||||
player,
|
||||
travelDestinations.get(player.worldObj.provider.dimensionId),
|
||||
0.087,
|
||||
maxMessageDistance);
|
||||
|
||||
for (Table.Cell<Double, Double, BlockCoord> cell : possibleDestinations.cellSet()) {
|
||||
if (cell.getColumnKey() <= maxDistance) {
|
||||
return Optional.of(cell.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (!possibleDestinations.isEmpty()) {
|
||||
// We found at least one block within maxMessageDistance, but no blocks within maxDistance.
|
||||
showMessage(player, new ChatComponentTranslation("enderio.blockTravelPlatform.outOfRange"));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/** Finds a valid destination near the provided vector, or returns empty optional if unsuccessful. */
|
||||
private Optional<BlockCoord> findNearbyDestination(EntityPlayer player, TravelSource source, Vector3d sample) {
|
||||
Optional<BlockCoord> destinationOptional = findValidDestination(
|
||||
player,
|
||||
source,
|
||||
new BlockCoord((int) Math.floor(sample.x), (int) Math.floor(sample.y), (int) Math.floor(sample.z)));
|
||||
if (destinationOptional.isPresent()) {
|
||||
return destinationOptional;
|
||||
}
|
||||
|
||||
destinationOptional = findValidDestination(
|
||||
player,
|
||||
source,
|
||||
new BlockCoord((int) Math.floor(sample.x), (int) Math.floor(sample.y) + 1, (int) Math.floor(sample.z)));
|
||||
if (destinationOptional.isPresent()) {
|
||||
return destinationOptional;
|
||||
}
|
||||
|
||||
if (!Config.travelStaffSearchOptimize) {
|
||||
destinationOptional = findValidDestination(
|
||||
player,
|
||||
source,
|
||||
new BlockCoord(
|
||||
(int) Math.floor(sample.x),
|
||||
(int) Math.floor(sample.y) - 1,
|
||||
(int) Math.floor(sample.z)));
|
||||
if (destinationOptional.isPresent()) {
|
||||
return destinationOptional;
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provided position if it's valid, or returns empty optional if unsuccessful.
|
||||
*
|
||||
* <p>
|
||||
* To be precise: if the destination is a travel anchor or other block, then the returned coordinates will be one
|
||||
* block higher, to place the player on top of the block.
|
||||
*/
|
||||
public Optional<BlockCoord> findValidDestination(EntityPlayer player, TravelSource source, BlockCoord coord) {
|
||||
// Are we trying to travel to a block (anchor or telepad)?
|
||||
boolean travelToBlock = source != TravelSource.STAFF_BLINK && source != TravelSource.TELEPORT_STAFF_BLINK;
|
||||
|
||||
BlockCoord destination = coord;
|
||||
if (travelToBlock) {
|
||||
TileEntity te = player.worldObj.getTileEntity(coord.x, coord.y, coord.z);
|
||||
if (te instanceof ITravelAccessable) {
|
||||
ITravelAccessable ta = (ITravelAccessable) te;
|
||||
if (!ta.canBlockBeAccessed(player)) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.gui.travelAccessable.unauthorised"));
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
// We actually want to go on top of the block.
|
||||
destination = coord.getLocation(ForgeDirection.UP);
|
||||
}
|
||||
|
||||
if (!isInRangeTarget(player, destination, source.getMaxDistanceTravelledSq())) {
|
||||
if (travelToBlock) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.blockTravelPlatform.outOfRange"));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
if (!isValidTarget(player, destination, source)) {
|
||||
if (travelToBlock) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.blockTravelPlatform.invalidTarget"));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(destination);
|
||||
}
|
||||
|
||||
public boolean travelToSelectedTarget(EntityPlayer player, TravelSource source, boolean conserveMomentum) {
|
||||
return travelToLocation(player, source, selectedCoord, conserveMomentum);
|
||||
}
|
||||
|
||||
public boolean travelToLocation(EntityPlayer player, TravelSource source, BlockCoord coord,
|
||||
boolean conserveMomentum) {
|
||||
|
||||
if (source != TravelSource.STAFF_BLINK && source != TravelSource.TELEPORT_STAFF_BLINK) {
|
||||
TileEntity te = player.worldObj.getTileEntity(coord.x, coord.y, coord.z);
|
||||
if (te instanceof ITravelAccessable) {
|
||||
ITravelAccessable ta = (ITravelAccessable) te;
|
||||
if (!ta.canBlockBeAccessed(player)) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.gui.travelAccessable.unauthorised"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Optional<BlockCoord> destinationOptional = findValidDestination(player, source, coord);
|
||||
if (!destinationOptional.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
BlockCoord destination = destinationOptional.get();
|
||||
|
||||
int requiredPower = 0;
|
||||
requiredPower = getRequiredPower(player, source, coord);
|
||||
requiredPower = getRequiredPower(player, source, destination);
|
||||
if (requiredPower < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isInRangeTarget(player, coord, source.getMaxDistanceTravelledSq())) {
|
||||
if (source != TravelSource.STAFF_BLINK && source != TravelSource.TELEPORT_STAFF_BLINK) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.blockTravelPlatform.outOfRange"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!isValidTarget(player, coord, source)) {
|
||||
if (source != TravelSource.STAFF_BLINK && source != TravelSource.TELEPORT_STAFF_BLINK) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.blockTravelPlatform.invalidTarget"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (doClientTeleport(player, coord, source, requiredPower, conserveMomentum)) {
|
||||
if (doClientTeleport(player, destinationOptional.get(), source, requiredPower, conserveMomentum)) {
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
player.worldObj.spawnParticle(
|
||||
"portal",
|
||||
@@ -764,6 +847,17 @@ public class TravelController {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isValidTarget(EntityPlayer player, BlockCoord bc, TravelSource source) {
|
||||
if (bc == null) {
|
||||
return false;
|
||||
}
|
||||
World w = player.worldObj;
|
||||
BlockCoord baseLoc = bc;
|
||||
|
||||
return canTeleportTo(player, source, baseLoc, w)
|
||||
&& canTeleportTo(player, source, baseLoc.getLocation(ForgeDirection.UP), w);
|
||||
}
|
||||
|
||||
public int getRequiredPower(EntityPlayer player, TravelSource source, BlockCoord coord) {
|
||||
if (!isTravelItemActive(player, true)) {
|
||||
return 0;
|
||||
@@ -808,21 +902,6 @@ public class TravelController {
|
||||
return Math.sqrt(getDistanceSquared(player, coord));
|
||||
}
|
||||
|
||||
private boolean isValidTarget(EntityPlayer player, BlockCoord bc, TravelSource source) {
|
||||
if (bc == null) {
|
||||
return false;
|
||||
}
|
||||
World w = player.worldObj;
|
||||
BlockCoord baseLoc = bc;
|
||||
if (source != TravelSource.STAFF_BLINK && source != TravelSource.TELEPORT_STAFF_BLINK) {
|
||||
// targeting a block so go one up
|
||||
baseLoc = bc.getLocation(ForgeDirection.UP);
|
||||
}
|
||||
|
||||
return canTeleportTo(player, source, baseLoc, w)
|
||||
&& canTeleportTo(player, source, baseLoc.getLocation(ForgeDirection.UP), w);
|
||||
}
|
||||
|
||||
private boolean canTeleportTo(EntityPlayer player, TravelSource source, BlockCoord bc, World w) {
|
||||
if (bc.y < 1) {
|
||||
return false;
|
||||
@@ -904,6 +983,7 @@ public class TravelController {
|
||||
if (selectedBlock instanceof ITravelAccessable) {
|
||||
ITravelAccessable travelBlock = (ITravelAccessable) selectedBlock;
|
||||
BlockCoord targetBlock = new BlockCoord(currentBlock.x, y, currentBlock.z);
|
||||
BlockCoord destination = targetBlock.getLocation(ForgeDirection.UP);
|
||||
|
||||
if (Config.travelAnchorSkipWarning) {
|
||||
if (travelBlock.getRequiresPassword(player)) {
|
||||
@@ -914,55 +994,67 @@ public class TravelController {
|
||||
&& !travelBlock.canUiBeAccessed(player)) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.gui.travelAccessable.skipPrivate"));
|
||||
}
|
||||
if (!isValidTarget(player, targetBlock, TravelSource.BLOCK)) {
|
||||
if (!isValidTarget(player, destination, TravelSource.BLOCK)) {
|
||||
showMessage(player, new ChatComponentTranslation("enderio.gui.travelAccessable.skipObstructed"));
|
||||
}
|
||||
}
|
||||
if (travelBlock.canBlockBeAccessed(player) && isValidTarget(player, targetBlock, TravelSource.BLOCK)) {
|
||||
if (travelBlock.canBlockBeAccessed(player) && isValidTarget(player, destination, TravelSource.BLOCK)) {
|
||||
return targetBlock;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a row-sorted table with angle in radians as the row, distance as the column, and block coordinate as the
|
||||
* value, holding all blocks which lie within the specified viewing angle and distance.
|
||||
*
|
||||
* <p>
|
||||
* The table is sorted by angle ascending, so the smallest angle will be first.
|
||||
*
|
||||
* @param player The player to search from.
|
||||
* @param blocks The blocks to search through.
|
||||
* @param maxAngle The maximum allowed angle, in radians.
|
||||
* @param maxDistance The maximum allowed distance.
|
||||
*/
|
||||
private RowSortedTable<Double, Double, BlockCoord> findBlocksWithinAngle(EntityPlayer player,
|
||||
Iterable<BlockCoord> blocks, double maxAngle, double maxDistance) {
|
||||
Vector3d eye = Util.getEyePositionEio(player);
|
||||
Vector3d look = Util.getLookVecEio(player);
|
||||
|
||||
// Table of angle, distance, and block coordinate holding found blocks.
|
||||
// Angle is the row, so this table will automatically be sorted by angle ascending.
|
||||
RowSortedTable<Double, Double, BlockCoord> foundBlocks = TreeBasedTable.create();
|
||||
|
||||
for (BlockCoord p : blocks) {
|
||||
Vector3d block = new Vector3d(p.x + 0.5, p.y + 0.5, p.z + 0.5);
|
||||
block.sub(eye);
|
||||
double distance = block.length();
|
||||
if (distance > maxDistance) {
|
||||
continue;
|
||||
}
|
||||
block.normalize();
|
||||
|
||||
double angle = Math.acos(look.dot(block));
|
||||
if (angle <= maxAngle) {
|
||||
foundBlocks.put(angle, distance, p);
|
||||
}
|
||||
}
|
||||
|
||||
return foundBlocks;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
private void updateSelectedTarget(EntityPlayer player) {
|
||||
selectedCoord = null;
|
||||
if (candidates.isEmpty()) {
|
||||
selectedCoord = null;
|
||||
return;
|
||||
}
|
||||
|
||||
double closestDistance = Double.MAX_VALUE;
|
||||
for (BlockCoord bc : candidates.keySet()) {
|
||||
if (!bc.equals(onBlockCoord)) {
|
||||
|
||||
double d = addRatio(bc);
|
||||
if (d < closestDistance) {
|
||||
selectedCoord = bc;
|
||||
closestDistance = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedCoord != null) {
|
||||
|
||||
Vector3d blockCenter = new Vector3d(selectedCoord.x + 0.5, selectedCoord.y + 0.5, selectedCoord.z + 0.5);
|
||||
Vector2d blockCenterPixel = currentView.getScreenPoint(blockCenter);
|
||||
|
||||
Vector2d screenMidPixel = new Vector2d(
|
||||
Minecraft.getMinecraft().displayWidth,
|
||||
Minecraft.getMinecraft().displayHeight);
|
||||
screenMidPixel.scale(0.5);
|
||||
|
||||
double pixDist = blockCenterPixel.distance(screenMidPixel);
|
||||
double rat = pixDist / Minecraft.getMinecraft().displayHeight;
|
||||
if (rat != rat) {
|
||||
rat = 0;
|
||||
}
|
||||
if (rat > 0.07) {
|
||||
selectedCoord = null;
|
||||
}
|
||||
}
|
||||
// Find the nearest travel anchor within roughly 10 degrees.
|
||||
Optional<BlockCoord> selectedBlock = findBlocksWithinAngle(player, candidates.keySet(), 0.175, Double.MAX_VALUE)
|
||||
.values().stream().findFirst();
|
||||
selectedCoord = selectedBlock.orElse(null);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@@ -1101,19 +1193,15 @@ public class TravelController {
|
||||
}
|
||||
|
||||
public static void showMessage(EntityPlayer player, IChatComponent chatComponent) {
|
||||
if (Loader.isModLoaded("gtnhlib")) {
|
||||
if (player instanceof EntityPlayerMP) {
|
||||
chatComponent.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.WHITE));
|
||||
GTNHLib.proxy.sendMessageAboveHotbar((EntityPlayerMP) player, chatComponent, 60, true, true);
|
||||
} else {
|
||||
GTNHLib.proxy.printMessageAboveHotbar(
|
||||
EnumChatFormatting.WHITE + chatComponent.getFormattedText(),
|
||||
60,
|
||||
true,
|
||||
true);
|
||||
}
|
||||
if (player instanceof EntityPlayerMP) {
|
||||
chatComponent.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.WHITE));
|
||||
GTNHLib.proxy.sendMessageAboveHotbar((EntityPlayerMP) player, chatComponent, 60, true, true);
|
||||
} else {
|
||||
player.addChatComponentMessage(chatComponent);
|
||||
GTNHLib.proxy.printMessageAboveHotbar(
|
||||
EnumChatFormatting.WHITE + chatComponent.getFormattedText(),
|
||||
60,
|
||||
true,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,6 +337,9 @@ public class TileTravelAnchor extends TileEntityEio implements ITravelAccessable
|
||||
public void validate() {
|
||||
super.validate();
|
||||
if (isTravelSource()) {
|
||||
// Note: travelDestinations is a SetMultimap, which does not allow duplicate entries.
|
||||
// So it's okay if this gets called multiple times with the same BlockCoord.
|
||||
// Though, I think that it's not currently getting called multiple times, anyway.
|
||||
TravelController.instance.travelDestinations.put(worldObj.provider.dimensionId, getLocation());
|
||||
}
|
||||
}
|
||||
@@ -346,10 +349,4 @@ public class TileTravelAnchor extends TileEntityEio implements ITravelAccessable
|
||||
super.invalidate();
|
||||
TravelController.instance.travelDestinations.remove(worldObj.provider.dimensionId, getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload() {
|
||||
super.onChunkUnload();
|
||||
TravelController.instance.travelDestinations.remove(worldObj.provider.dimensionId, getLocation());
|
||||
}
|
||||
}
|
||||
+107
-33
@@ -7,7 +7,10 @@ import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.play.server.S12PacketEntityVelocity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import com.enderio.core.common.util.BlockCoord;
|
||||
import com.enderio.core.common.util.Util;
|
||||
@@ -18,6 +21,7 @@ import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
|
||||
import crazypants.enderio.Log;
|
||||
import crazypants.enderio.api.teleport.IItemOfTravel;
|
||||
import crazypants.enderio.api.teleport.ITravelAccessable;
|
||||
import crazypants.enderio.api.teleport.TeleportEntityEvent;
|
||||
import crazypants.enderio.api.teleport.TravelSource;
|
||||
import crazypants.enderio.teleport.ItemTeleportStaff;
|
||||
@@ -30,13 +34,27 @@ public class PacketLongDistanceTravelEvent
|
||||
boolean conserveMotion;
|
||||
int entityId;
|
||||
int source;
|
||||
// Below values are for also attempting a regular blink if the long-distance anchor check fails.
|
||||
boolean alsoDoTeleport;
|
||||
int tpX;
|
||||
int tpY;
|
||||
int tpZ;
|
||||
|
||||
public PacketLongDistanceTravelEvent() {}
|
||||
|
||||
public PacketLongDistanceTravelEvent(Entity entity, boolean conserveMotion, TravelSource source) {
|
||||
this(entity, conserveMotion, source, false, 0, 0, 0);
|
||||
}
|
||||
|
||||
public PacketLongDistanceTravelEvent(Entity entity, boolean conserveMotion, TravelSource source,
|
||||
boolean alsoDoTeleport, int tpX, int tpY, int tpZ) {
|
||||
this.conserveMotion = conserveMotion;
|
||||
this.entityId = entity instanceof EntityPlayer ? -1 : entity.getEntityId();
|
||||
this.source = source.ordinal();
|
||||
this.alsoDoTeleport = alsoDoTeleport;
|
||||
this.tpX = tpX;
|
||||
this.tpY = tpY;
|
||||
this.tpZ = tpZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,6 +62,10 @@ public class PacketLongDistanceTravelEvent
|
||||
buf.writeBoolean(conserveMotion);
|
||||
buf.writeInt(entityId);
|
||||
buf.writeInt(source);
|
||||
buf.writeBoolean(alsoDoTeleport);
|
||||
buf.writeInt(tpX);
|
||||
buf.writeInt(tpY);
|
||||
buf.writeInt(tpZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,6 +73,10 @@ public class PacketLongDistanceTravelEvent
|
||||
conserveMotion = buf.readBoolean();
|
||||
entityId = buf.readInt();
|
||||
source = buf.readInt();
|
||||
alsoDoTeleport = buf.readBoolean();
|
||||
tpX = buf.readInt();
|
||||
tpY = buf.readInt();
|
||||
tpZ = buf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,7 +95,14 @@ public class PacketLongDistanceTravelEvent
|
||||
|
||||
TravelSource source = TravelSource.values()[message.source];
|
||||
|
||||
if (!validate(toTp, source)) {
|
||||
if (!validate(
|
||||
toTp,
|
||||
source,
|
||||
message.conserveMotion,
|
||||
message.alsoDoTeleport,
|
||||
message.tpX,
|
||||
message.tpY,
|
||||
message.tpZ)) {
|
||||
Log.LOGGER.warn(
|
||||
Log.securityMarker,
|
||||
"Player {} tried to tp without valid prereq.",
|
||||
@@ -77,35 +110,82 @@ public class PacketLongDistanceTravelEvent
|
||||
return null;
|
||||
}
|
||||
|
||||
doServerTeleport(toTp, message.conserveMotion, source);
|
||||
doServerTeleport(
|
||||
toTp,
|
||||
message.conserveMotion,
|
||||
source,
|
||||
message.alsoDoTeleport,
|
||||
message.tpX,
|
||||
message.tpY,
|
||||
message.tpZ);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean validate(EntityPlayerMP toTp, TravelSource source) {
|
||||
private static boolean validate(EntityPlayerMP toTp, TravelSource source, boolean conserveMotion,
|
||||
boolean alsoDoTeleport, int tpX, int tpY, int tpZ) {
|
||||
ItemStack equippedItem = toTp.getCurrentEquippedItem();
|
||||
switch (source) {
|
||||
case STAFF:
|
||||
// Not allowed to do teleport staff teleport with regular staff.
|
||||
if (alsoDoTeleport) {
|
||||
return false;
|
||||
}
|
||||
return equippedItem != null && equippedItem.getItem() instanceof IItemOfTravel
|
||||
&& ((IItemOfTravel) equippedItem.getItem()).isActive(toTp, equippedItem);
|
||||
case TELEPORT_STAFF:
|
||||
// tp staff is creative version of traveling staff
|
||||
// no energy check or anything else needed
|
||||
// but the player must actually be equipped with one of these
|
||||
if (alsoDoTeleport) {
|
||||
String error = TravelController.instance
|
||||
.validatePacketTravelEvent(toTp, tpX, tpY, tpZ, 0, conserveMotion, source);
|
||||
if (error != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return equippedItem != null && equippedItem.getItem() instanceof ItemTeleportStaff;
|
||||
|
||||
default:
|
||||
// all other types are not allowed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean doServerTeleport(Entity toTp, boolean conserveMotion, TravelSource source) {
|
||||
EntityPlayer player = toTp instanceof EntityPlayer ? (EntityPlayer) toTp : null;
|
||||
Optional<BlockCoord> travelDestination = TravelController.instance.findTravelDestination(player, source);
|
||||
if (!travelDestination.isPresent()) {
|
||||
public static boolean doServerTeleport(Entity toTp, boolean conserveMotion, TravelSource source,
|
||||
boolean alsoDoTeleport, int tpX, int tpY, int tpZ) {
|
||||
if (!(toTp instanceof EntityPlayer)) {
|
||||
return false;
|
||||
}
|
||||
BlockCoord destination = travelDestination.get();
|
||||
EntityPlayer player = (EntityPlayer) toTp;
|
||||
|
||||
Optional<BlockCoord> travelDestination = TravelController.instance.findTravelDestination(player, source);
|
||||
if (!travelDestination.isPresent()) {
|
||||
if (alsoDoTeleport) {
|
||||
return PacketTravelEvent.doServerTeleport(toTp, tpX, tpY, tpZ, 0, conserveMotion, source);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockCoord targetBlock = travelDestination.get();
|
||||
TileEntity te = player.worldObj.getTileEntity(targetBlock.x, targetBlock.y, targetBlock.z);
|
||||
if (te instanceof ITravelAccessable) {
|
||||
ITravelAccessable ta = (ITravelAccessable) te;
|
||||
if (!ta.canBlockBeAccessed(player)) {
|
||||
TravelController
|
||||
.showMessage(player, new ChatComponentTranslation("enderio.gui.travelAccessable.unauthorised"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We're teleporting to a block, so go one above.
|
||||
BlockCoord destination = targetBlock.getLocation(ForgeDirection.UP);
|
||||
if (!TravelController.instance.isValidTarget(player, destination, source)) {
|
||||
TravelController
|
||||
.showMessage(player, new ChatComponentTranslation("enderio.blockTravelPlatform.invalidTarget"));
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = destination.x;
|
||||
int y = destination.y;
|
||||
int z = destination.z;
|
||||
@@ -113,7 +193,7 @@ public class PacketLongDistanceTravelEvent
|
||||
if (powerUse < 0) {
|
||||
return false;
|
||||
}
|
||||
if (player != null && player.getCurrentEquippedItem() != null
|
||||
if (player.getCurrentEquippedItem() != null
|
||||
&& player.getCurrentEquippedItem().getItem() instanceof IItemOfTravel) {
|
||||
int used = ((IItemOfTravel) player.getCurrentEquippedItem().getItem())
|
||||
.canExtractInternal(player.getCurrentEquippedItem(), powerUse);
|
||||
@@ -134,32 +214,26 @@ public class PacketLongDistanceTravelEvent
|
||||
|
||||
toTp.playSound(source.sound, 1.0F, 1.0F);
|
||||
|
||||
if (player != null) {
|
||||
player.setPositionAndUpdate(x + 0.5, y + 1.1, z + 0.5);
|
||||
} else {
|
||||
toTp.setPosition(x, y, z);
|
||||
player.setPositionAndUpdate(x + 0.5, y + 0.1, z + 0.5);
|
||||
|
||||
player.worldObj.playSoundEffect(x, y, z, source.sound, 1.0F, 1.0F);
|
||||
player.fallDistance = 0;
|
||||
|
||||
if (conserveMotion) {
|
||||
Vector3d velocityVex = Util.getLookVecEio(player);
|
||||
S12PacketEntityVelocity p = new S12PacketEntityVelocity(
|
||||
toTp.getEntityId(),
|
||||
velocityVex.x,
|
||||
velocityVex.y,
|
||||
velocityVex.z);
|
||||
((EntityPlayerMP) player).playerNetServerHandler.sendPacket(p);
|
||||
}
|
||||
|
||||
toTp.worldObj.playSoundEffect(x, y, z, source.sound, 1.0F, 1.0F);
|
||||
toTp.fallDistance = 0;
|
||||
|
||||
if (player != null) {
|
||||
if (conserveMotion) {
|
||||
Vector3d velocityVex = Util.getLookVecEio(player);
|
||||
S12PacketEntityVelocity p = new S12PacketEntityVelocity(
|
||||
toTp.getEntityId(),
|
||||
velocityVex.x,
|
||||
velocityVex.y,
|
||||
velocityVex.z);
|
||||
((EntityPlayerMP) player).playerNetServerHandler.sendPacket(p);
|
||||
}
|
||||
|
||||
if (powerUse > 0 && player.getCurrentEquippedItem() != null
|
||||
&& player.getCurrentEquippedItem().getItem() instanceof IItemOfTravel) {
|
||||
ItemStack item = player.getCurrentEquippedItem().copy();
|
||||
((IItemOfTravel) item.getItem()).extractInternal(item, powerUse);
|
||||
toTp.setCurrentItemOrArmor(0, item);
|
||||
}
|
||||
if (powerUse > 0 && player.getCurrentEquippedItem() != null
|
||||
&& player.getCurrentEquippedItem().getItem() instanceof IItemOfTravel) {
|
||||
ItemStack item = player.getCurrentEquippedItem().copy();
|
||||
((IItemOfTravel) item.getItem()).extractInternal(item, powerUse);
|
||||
toTp.setCurrentItemOrArmor(0, item);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -118,7 +118,7 @@ public class PacketTravelEvent implements IMessage, IMessageHandler<PacketTravel
|
||||
toTp.playSound(source.sound, 1.0F, 1.0F);
|
||||
|
||||
if (player != null) {
|
||||
player.setPositionAndUpdate(x + 0.5, y + 1.1, z + 0.5);
|
||||
player.setPositionAndUpdate(x + 0.5, y + 0.1, z + 0.5);
|
||||
} else {
|
||||
toTp.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package crazypants.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.particle.EffectRenderer;
|
||||
import net.minecraft.client.particle.EntityPortalFX;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import com.enderio.core.common.util.BlockCoord;
|
||||
|
||||
@@ -47,18 +51,35 @@ public class ClientUtil {
|
||||
con.readFromNBT(pkt.tc, TileConduitBundle.NBT_VERSION);
|
||||
}
|
||||
|
||||
public static void spawnFarmParcticles(Random rand, BlockCoord bc) {
|
||||
double xOff = 0.5 + (rand.nextDouble() - 0.5) * 1.1;
|
||||
double yOff = 0.5 + (rand.nextDouble() - 0.5) * 0.2;
|
||||
double zOff = 0.5 + (rand.nextDouble() - 0.5) * 1.1;
|
||||
Minecraft.getMinecraft().theWorld.spawnParticle(
|
||||
"portal",
|
||||
bc.x + xOff,
|
||||
bc.y + yOff,
|
||||
bc.z + zOff,
|
||||
(rand.nextDouble() - 0.5) * 1.5,
|
||||
-rand.nextDouble(),
|
||||
(rand.nextDouble() - 0.5) * 1.5);
|
||||
public static void spawnFarmParticles(Random rand, List<BlockCoord> coords, int particlesCount) {
|
||||
// 0 = All, 1 = Decreased, 2 = Minimal
|
||||
int particleSetting = Minecraft.getMinecraft().gameSettings.particleSetting;
|
||||
if (particleSetting >= 2 /* Minimal */) {
|
||||
return;
|
||||
}
|
||||
|
||||
int particles = particleSetting == 0 ? particlesCount /* All */
|
||||
: (particlesCount / 2) /* Decreased */;
|
||||
|
||||
World world = Minecraft.getMinecraft().theWorld;
|
||||
EffectRenderer effectRenderer = Minecraft.getMinecraft().effectRenderer;
|
||||
|
||||
for (BlockCoord bc : coords) {
|
||||
for (int i = 0; i < particles; i++) {
|
||||
double xOff = 0.5 + (rand.nextDouble() - 0.5) * 1.1;
|
||||
double yOff = 0.5 + (rand.nextDouble() - 0.5) * 0.2;
|
||||
double zOff = 0.5 + (rand.nextDouble() - 0.5) * 1.1;
|
||||
effectRenderer.addEffect(
|
||||
new EntityPortalFX(
|
||||
world,
|
||||
bc.x + xOff,
|
||||
bc.y + yOff,
|
||||
bc.z + zOff,
|
||||
(rand.nextDouble() - 0.5) * 1.5,
|
||||
-rand.nextDouble(),
|
||||
(rand.nextDouble() - 0.5) * 1.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setTankNBT(PacketCombustionTank message, int x, int y, int z) {
|
||||
|
||||
@@ -150,7 +150,7 @@ enderio.silicon.name=Silicon
|
||||
enderio.conduitBinder.name=Conduit Binder
|
||||
enderio.binderComposite.name=Binder Composite
|
||||
enderio.phasedIronNugget.name=Pulsating Iron Nugget
|
||||
tile.blockDarkIronBars.name=Dark Iron Bars
|
||||
tile.blockDarkIronBars.name=Dark Steel Bars
|
||||
tile.blockSoulariumBars.name=Soularium Bars
|
||||
tile.blockEndSteelBars.name=End Steel Bars
|
||||
tile.blockEndermanSkull.name=Enderman Skull
|
||||
|
||||
Reference in new issue
Block a user