Improved world border usability
- use action bar to reduce chat spamming - inform player when cancelling nether portal opening - render the celestia object border using vanilla renderer
This commit is contained in:
parent
7dc6567b5e
commit
d5a8b5e18d
12 changed files with 241 additions and 9 deletions
|
@ -36,6 +36,7 @@ public class ClassTransformer implements net.minecraft.launchwrapper.IClassTrans
|
|||
|
||||
private static final String GRAVITY_MANAGER_CLASS = "cr0s/warpdrive/data/GravityManager";
|
||||
private static final String CLOAK_MANAGER_CLASS = "cr0s/warpdrive/data/CloakManager";
|
||||
private static final String CELESTIAL_OBJECT_MANAGER_CLASS = "cr0s/warpdrive/data/CelestialObjectManager";
|
||||
|
||||
private static final boolean debugLog = false;
|
||||
private static final String ASM_DUMP_BEFORE = "asm/warpdrive.before";
|
||||
|
@ -69,6 +70,12 @@ public class ClassTransformer implements net.minecraft.launchwrapper.IClassTrans
|
|||
nodeMap.put("ForgeHooks.class", "ForgeHooks");
|
||||
nodeMap.put("loadAdvancements.name", "lambda$loadAdvancements$0");
|
||||
nodeMap.put("loadAdvancements.desc", "(Lnet/minecraftforge/fml/common/ModContainer;Ljava/util/Map;Ljava/nio/file/Path;Ljava/nio/file/Path;)Ljava/lang/Boolean;");
|
||||
|
||||
nodeMap.put("RenderGlobal.class", "buw");
|
||||
nodeMap.put("renderWorldBorder.name", "func_180449_a");
|
||||
nodeMap.put("renderWorldBorder.desc", "(Lnet/minecraft/entity/Entity;F)V");
|
||||
nodeMap.put("getWorldBorder.name", "func_175723_af");
|
||||
nodeMap.put("getWorldBorder.desc", "()Lnet/minecraft/world/border/WorldBorder;");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -119,6 +126,10 @@ public class ClassTransformer implements net.minecraft.launchwrapper.IClassTrans
|
|||
bytesNew = transformMinecraftForgeHooks(bytesOld);
|
||||
break;
|
||||
|
||||
case "net.minecraft.client.renderer.RenderGlobal":
|
||||
bytesNew = transformMinecraftRenderGlobal(bytesOld);
|
||||
break;
|
||||
|
||||
default:
|
||||
bytesNew = null;
|
||||
}
|
||||
|
@ -743,6 +754,62 @@ public class ClassTransformer implements net.minecraft.launchwrapper.IClassTrans
|
|||
return bytesNew;
|
||||
}
|
||||
|
||||
private byte[] transformMinecraftRenderGlobal(@Nonnull final byte[] bytes) {
|
||||
final ClassNode classNode = new ClassNode();
|
||||
final ClassReader classReader = new ClassReader(bytes);
|
||||
classReader.accept(classNode, 0);
|
||||
|
||||
final int countExpected = 1;
|
||||
int countTransformed = 0;
|
||||
for (final MethodNode methodNode : classNode.methods) {
|
||||
// if (debugLog) { FMLLoadingPlugin.logger.info(String.format("- Method %s %s", methodNode.name, methodNode.desc)); }
|
||||
|
||||
if ( (methodNode.name.equals(nodeMap.get("renderWorldBorder.name")) || methodNode.name.equals("renderWorldBorder"))
|
||||
&& methodNode.desc.equals(nodeMap.get("renderWorldBorder.desc")) ) {
|
||||
FMLLoadingPlugin.logger.debug(String.format("Found method to transform: %s %s",
|
||||
methodNode.name, methodNode.desc));
|
||||
|
||||
int indexInstruction = 0;
|
||||
|
||||
while (indexInstruction < methodNode.instructions.size()) {
|
||||
final AbstractInsnNode abstractNode = methodNode.instructions.get(indexInstruction);
|
||||
if (debugLog) { decompile(abstractNode); }
|
||||
|
||||
// change WorldBorder worldborder = this.field_72769_h.func_175723_af();
|
||||
// into WorldBorder worldborder = CelestiaObjectManager.getWorldBorder(world);
|
||||
if (abstractNode instanceof MethodInsnNode) {
|
||||
final MethodInsnNode nodeAt = (MethodInsnNode) abstractNode;
|
||||
|
||||
if (nodeAt.name.equals(nodeMap.get("getWorldBorder.name")) || nodeAt.name.equals("getWorldBorder")) {
|
||||
final MethodInsnNode overwriteNode = new MethodInsnNode(
|
||||
Opcodes.INVOKESTATIC,
|
||||
CELESTIAL_OBJECT_MANAGER_CLASS,
|
||||
"World_getWorldBorder",
|
||||
"(Lnet/minecraft/world/World;)Lnet/minecraft/world/border/WorldBorder;",
|
||||
false);
|
||||
methodNode.instructions.set(nodeAt, overwriteNode);
|
||||
if (debugLog) { FMLLoadingPlugin.logger.info(String.format("Injecting into %s.%s %s", classNode.name, methodNode.name, methodNode.desc)); }
|
||||
countTransformed++;
|
||||
}
|
||||
}
|
||||
|
||||
indexInstruction++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (countTransformed != countExpected) {
|
||||
FMLLoadingPlugin.logger.error(String.format("Transformation failed for %s (%d/%d), aborting...", classNode.name, countTransformed, countExpected));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); // | ClassWriter.COMPUTE_FRAMES);
|
||||
classNode.accept(writer);
|
||||
final byte[] bytesNew = writer.toByteArray();
|
||||
FMLLoadingPlugin.logger.info(String.format("Successful injection in %s", classNode.name));
|
||||
return bytesNew;
|
||||
}
|
||||
|
||||
private void removeInstruction(@Nonnull final MethodNode methodNode, final int indexInstruction) {
|
||||
final AbstractInsnNode abstractNodeToRemove = methodNode.instructions.get(indexInstruction);
|
||||
if (debugLog) {
|
||||
|
|
113
src/main/java/cr0s/warpdrive/data/CelestialBorder.java
Normal file
113
src/main/java/cr0s/warpdrive/data/CelestialBorder.java
Normal file
|
@ -0,0 +1,113 @@
|
|||
package cr0s.warpdrive.data;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.world.border.EnumBorderStatus;
|
||||
import net.minecraft.world.border.WorldBorder;
|
||||
|
||||
|
||||
/**
|
||||
* An overloaded world border to allow rectangular shapes.
|
||||
*
|
||||
* @author LemADEC
|
||||
*/
|
||||
public class CelestialBorder extends WorldBorder {
|
||||
|
||||
public int centerX, centerZ;
|
||||
public int radiusX, radiusZ;
|
||||
|
||||
public CelestialBorder(final int centerX, final int centerZ,
|
||||
final int radiusX, final int radiusZ) {
|
||||
this.centerX = centerX;
|
||||
this.centerZ = centerZ;
|
||||
this.radiusX = radiusX;
|
||||
this.radiusZ = radiusZ;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public EnumBorderStatus getStatus() {
|
||||
return EnumBorderStatus.STATIONARY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double minX() {
|
||||
return centerX - radiusX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double minZ() {
|
||||
return centerZ - radiusZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double maxX() {
|
||||
return centerX + radiusX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double maxZ() {
|
||||
return centerZ + radiusZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCenterX()
|
||||
{
|
||||
return centerX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCenterZ()
|
||||
{
|
||||
return centerZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCenter(final double x, final double z) {
|
||||
assert false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDiameter() {
|
||||
assert false;
|
||||
return super.getDiameter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeUntilTarget() {
|
||||
assert false;
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTargetSize() {
|
||||
return 2 * Math.max(radiusX, radiusZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransition(final double newSize) {
|
||||
super.setTransition(newSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransition(final double oldSize, final double newSize, final long time) {
|
||||
super.setTransition(oldSize, newSize, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSize(final int size) {
|
||||
// no operation
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 2 * Math.max(radiusX, radiusZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("CelestialBorder [@ %d %d Border(%d %d)]",
|
||||
centerX, centerZ,
|
||||
2 * radiusX, 2 * radiusZ );
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import net.minecraft.nbt.NBTTagList;
|
|||
import net.minecraft.util.IStringSerializable;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.world.border.WorldBorder;
|
||||
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
|
||||
|
@ -81,6 +82,7 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti
|
|||
public CelestialObject parent;
|
||||
private boolean isHyperspace;
|
||||
|
||||
private WorldBorder cache_worldBorder;
|
||||
private AxisAlignedBB cache_aabbWorldBorder;
|
||||
private AxisAlignedBB cache_aabbAreaToReachParent;
|
||||
private AxisAlignedBB cache_aabbAreaInParent;
|
||||
|
@ -485,6 +487,13 @@ public class CelestialObject implements Cloneable, IStringSerializable, ICelesti
|
|||
return new VectorI(dimensionCenterX - parentCenterX, 0, dimensionCenterZ - parentCenterZ);
|
||||
}
|
||||
|
||||
public WorldBorder getWorldBorder() {
|
||||
if (cache_worldBorder == null) {
|
||||
cache_worldBorder = new CelestialBorder(dimensionCenterX, dimensionCenterZ, borderRadiusX, borderRadiusZ);
|
||||
}
|
||||
return cache_worldBorder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getWorldBorderArea() {
|
||||
if (cache_aabbWorldBorder == null) {
|
||||
|
|
|
@ -2,11 +2,14 @@ package cr0s.warpdrive.data;
|
|||
|
||||
import cr0s.warpdrive.Commons;
|
||||
import cr0s.warpdrive.WarpDrive;
|
||||
import cr0s.warpdrive.api.WarpDriveText;
|
||||
import cr0s.warpdrive.config.InvalidXmlException;
|
||||
import cr0s.warpdrive.config.XmlFileManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
@ -22,6 +25,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
|||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.border.WorldBorder;
|
||||
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
|
@ -172,6 +176,14 @@ public class CelestialObjectManager extends XmlFileManager {
|
|||
final CelestialObject celestialObjectPortal = get(world, blockPos.getX(), blockPos.getZ());
|
||||
if (celestialObjectPortal != null) {
|
||||
if (!celestialObjectPortal.isInsideBorder(blockPos.getX(), blockPos.getZ()) ) {
|
||||
final EntityPlayer entityPlayer = world.getClosestPlayer(blockPos.getX(), blockPos.getY(), blockPos.getZ(), 10.0D, false);
|
||||
if (entityPlayer != null) {
|
||||
entityPlayer.sendStatusMessage(
|
||||
new WarpDriveText(Commons.getStyleWarning(), "warpdrive.world_border.portal_denied"), true);
|
||||
}
|
||||
WarpDrive.logger.info(String.format("Nether portal opening cancelled %s for player %s: portal entry is outside the world border",
|
||||
entityPlayer == null ? "-null-" : entityPlayer.getName(),
|
||||
Commons.format(world, blockPos) ));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -187,6 +199,14 @@ public class CelestialObjectManager extends XmlFileManager {
|
|||
final int zExit = (int) Math.floor(blockPos.getZ() * factor);
|
||||
if ( Math.abs(xExit - celestialObjectExit.dimensionCenterX) > celestialObjectExit.borderRadiusX
|
||||
|| Math.abs(zExit - celestialObjectExit.dimensionCenterZ) > celestialObjectExit.borderRadiusZ ) {
|
||||
final EntityPlayer entityPlayer = world.getClosestPlayer(blockPos.getX(), blockPos.getY(), blockPos.getZ(), 10.0D, false);
|
||||
if (entityPlayer != null) {
|
||||
entityPlayer.sendStatusMessage(
|
||||
new WarpDriveText(Commons.getStyleWarning(), "warpdrive.world_border.portal_denied"), true);
|
||||
}
|
||||
WarpDrive.logger.info(String.format("Nether portal opening cancelled for player %s %s: portal exit is outside the world border",
|
||||
entityPlayer == null ? "-null-" : entityPlayer.getName(),
|
||||
Commons.format(world, blockPos) ));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +238,22 @@ public class CelestialObjectManager extends XmlFileManager {
|
|||
return CLIENT.celestialObjects;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") // Core mod
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static WorldBorder World_getWorldBorder(@Nonnull final World world) {
|
||||
final WorldBorder worldBorder = world.getWorldBorder();
|
||||
final EntityPlayer entityPlayer = Minecraft.getMinecraft().player;
|
||||
if ( entityPlayer == null
|
||||
|| entityPlayer.world != world ) {
|
||||
return worldBorder;
|
||||
}
|
||||
final CelestialObject celestialObject = get(world, (int) entityPlayer.posX, (int) entityPlayer.posZ);
|
||||
if (celestialObject == null) {
|
||||
return worldBorder;
|
||||
}
|
||||
return celestialObject.getWorldBorder();
|
||||
}
|
||||
|
||||
// *** non-static methods ***
|
||||
|
||||
private void addOrUpdateInRegistry(@Nonnull final CelestialObject celestialObject, final boolean isUpdating) {
|
||||
|
|
|
@ -112,17 +112,17 @@ public class LivingHandler {
|
|||
if ( Math.abs(distanceSquared) <= BORDER_WARNING_RANGE_BLOCKS_SQUARED
|
||||
&& entityLivingBase instanceof EntityPlayer
|
||||
&& entityLivingBase.ticksExisted % 40 == 0) {
|
||||
Commons.addChatMessage( entityLivingBase,
|
||||
new WarpDriveText(Commons.getStyleWarning(), "warpdrive.world_border.in_range",
|
||||
(int) Math.sqrt(Math.abs(distanceSquared))) );
|
||||
((EntityPlayer) entityLivingBase).sendStatusMessage(
|
||||
new WarpDriveText(Commons.getStyleWarning(), "warpdrive.world_border.in_range",
|
||||
(int) Math.sqrt(Math.abs(distanceSquared))), true );
|
||||
}
|
||||
} else {
|
||||
if (entityLivingBase instanceof EntityPlayerMP) {
|
||||
if (((EntityPlayerMP) entityLivingBase).capabilities.isCreativeMode) {
|
||||
if (entityLivingBase.ticksExisted % 100 == 0) {
|
||||
Commons.addChatMessage( entityLivingBase,
|
||||
new WarpDriveText(Commons.getStyleWarning(), "warpdrive.world_border.outside",
|
||||
(int) Math.sqrt(Math.abs(distanceSquared))) );
|
||||
((EntityPlayer) entityLivingBase).sendStatusMessage(
|
||||
new WarpDriveText(Commons.getStyleWarning(), "warpdrive.world_border.outside",
|
||||
(int) Math.sqrt(Math.abs(distanceSquared))), true );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -980,4 +980,5 @@ warpdrive.transporter_signature.set=Transporter room is now linked to %1$s.
|
|||
|
||||
warpdrive.world_border.in_range=Proximity alert: world border is only %1$d m away!
|
||||
warpdrive.world_border.outside=You're %1$d m outside the world border...
|
||||
warpdrive.world_border.portal_denied=Portal opening cancelled to prevent a certain death!
|
||||
warpdrive.world_border.reached=You've reached the world border...
|
||||
|
|
|
@ -980,4 +980,5 @@ warpdrive.transporter_signature.set=Transporter room is now linked to %1$s.
|
|||
|
||||
warpdrive.world_border.in_range=Proximity alert: world border is only %1$d m away!
|
||||
warpdrive.world_border.outside=You're %1$d m outside the world border...
|
||||
warpdrive.world_border.portal_denied=Portal opening cancelled to prevent a certain death!
|
||||
warpdrive.world_border.reached=You've reached the world border...
|
||||
|
|
|
@ -978,6 +978,7 @@ warpdrive.transporter_signature.set_self=Transporter room can't target itself!
|
|||
warpdrive.transporter_signature.set_same=Transporter room is already linked to %1$s.
|
||||
warpdrive.transporter_signature.set=Transporter room is now linked to %1$s.
|
||||
|
||||
warpdrive.world_border.in_range=Proximity alert: world border is only %1$d m away!
|
||||
warpdrive.world_border.outside=You're %1$d m outside the world border...
|
||||
warpdrive.world_border.reached=You've reached the world border...
|
||||
warpdrive.world_border.in_range=Alerte de proximité: frontière du monde à %1$d m!
|
||||
warpdrive.world_border.outside=Tu es %1$d m au-delà de la frontière du monde...
|
||||
warpdrive.world_border.portal_denied=Ouverture du portail annulée pour éviter une mort certaine!
|
||||
warpdrive.world_border.reached=Tu as atteint la frontière du monde...
|
||||
|
|
|
@ -979,4 +979,5 @@ warpdrive.transporter_signature.set=Transporter room is now linked to %1$s.
|
|||
|
||||
warpdrive.world_border.in_range=Proximity alert: world border is only %1$d m away!
|
||||
warpdrive.world_border.outside=You're %1$d m outside the world border...
|
||||
warpdrive.world_border.portal_denied=Portal opening cancelled to prevent a certain death!
|
||||
warpdrive.world_border.reached=You've reached the world border...
|
||||
|
|
|
@ -980,4 +980,5 @@ warpdrive.transporter_signature.set=Transporter room is now linked to %1$s.
|
|||
|
||||
warpdrive.world_border.in_range=Proximity alert: world border is only %1$d m away!
|
||||
warpdrive.world_border.outside=You're %1$d m outside the world border...
|
||||
warpdrive.world_border.portal_denied=Portal opening cancelled to prevent a certain death!
|
||||
warpdrive.world_border.reached=You've reached the world border...
|
||||
|
|
|
@ -985,4 +985,5 @@ warpdrive.transporter_signature.set=Transporter room is now linked to %1$s.
|
|||
|
||||
warpdrive.world_border.in_range=Proximity alert: world border is only %1$d m away!
|
||||
warpdrive.world_border.outside=You're %1$d m outside the world border...
|
||||
warpdrive.world_border.portal_denied=Portal opening cancelled to prevent a certain death!
|
||||
warpdrive.world_border.reached=You've reached the world border...
|
||||
|
|
|
@ -979,4 +979,5 @@ warpdrive.transporter_signature.set=Transporter room is now linked to %1$s.
|
|||
|
||||
warpdrive.world_border.in_range=Proximity alert: world border is only %1$d m away!
|
||||
warpdrive.world_border.outside=You're %1$d m outside the world border...
|
||||
warpdrive.world_border.portal_denied=Portal opening cancelled to prevent a certain death!
|
||||
warpdrive.world_border.reached=You've reached the world border...
|
||||
|
|
Loading…
Reference in a new issue