Skip to content
This repository has been archived by the owner on Apr 7, 2021. It is now read-only.

World border #540

Draft
wants to merge 1 commit into
base: rewrite
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions proxy/src/main/java/org/dragonet/proxy/DragonProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.BedrockServer;
import com.nukkitx.protocol.bedrock.v389.Bedrock_v389;
Expand Down
2 changes: 2 additions & 0 deletions proxy/src/main/java/org/dragonet/proxy/TickerThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
package org.dragonet.proxy;

import com.nukkitx.math.vector.Vector2f;
import com.nukkitx.math.vector.Vector3f;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.network.session.ProxySession;
Expand Down
86 changes: 86 additions & 0 deletions proxy/src/main/java/org/dragonet/proxy/data/WorldBorder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package org.dragonet.proxy.data;

import com.nukkitx.math.vector.Vector2f;
import com.nukkitx.math.vector.Vector3f;
import lombok.*;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.session.cache.object.CachedEntity;
import org.dragonet.proxy.network.session.cache.object.CachedPlayer;
import org.dragonet.proxy.util.TextFormat;

@Getter
@Setter
@RequiredArgsConstructor
public class WorldBorder {
@NonNull private Vector2f center;
@NonNull private double radius;
@NonNull private double oldRadius;
@NonNull private double newRadius;
@NonNull private long speed;
@NonNull private int warningTime;
@NonNull private int warningBlocks;

private double minX, minZ, maxX, maxZ;

/**
* Called every tick to tell the player if they are near the border edge.
*/
public void onTick(ProxySession session) {
CachedPlayer player = session.getCachedEntity();
if(isNearEdge(player)) {
session.sendActionBar(TextFormat.BOLD + "" + TextFormat.RED + "You are near the world border (" + (int) getDistanceToEdge(player) + " blocks)", 0);
}
}

/**
* Updates the min and max positions of the world border.
* This should be called every time there is a modifcation to either the center coordinates or the radius.
*/
public void update() {
this.minX = Math.max(center.getX() - newRadius / 2.0D, -newRadius);
this.minZ = Math.max(center.getY() - newRadius / 2.0D, -newRadius);
this.maxX = Math.min(center.getX() + newRadius / 2.0D, newRadius);
this.maxZ = Math.min(center.getY() + newRadius / 2.0D, newRadius);
}

/**
* Checks if an entity is within the warning distance to the edge of the world border.
* https://wiki.vg/Protocol#World_Border
*/
public boolean isNearEdge(CachedEntity entity) {
double distance = Math.max(Math.min(speed * 1000 * warningTime, Math.abs(newRadius - oldRadius)), warningBlocks);

float entityDistance = (float) getDistanceToEdge(entity);

if ((double) entityDistance < distance) {
return true;
}
return false;
}

/**
* Checks if an entity is inside the world border.
*
* This method needs to be improved as it doesn't account for when the world border
* is currently changing size, it only accounts for the target size.
*
* Something similar to the method above should work.
*/
public boolean isInsideBorder(CachedEntity entity) {
return entity.getPosition().getX() > minX && entity.getPosition().getX() < maxX && entity.getPosition().getZ() > minZ && entity.getPosition().getZ() < maxZ;
}

/**
* Calculates how close the entity is to the edge of the world border.
*/
public double getDistanceToEdge(CachedEntity entity) {
Vector3f pos = entity.getPosition();

double minPosZ = pos.getZ() - minZ;
double maxPosZ = maxZ - pos.getZ();
double minPosX = pos.getX() - minX;
double maxPosX = maxX - pos.getX();

return Math.min(Math.min(Math.min(minPosX, maxPosX), minPosZ), maxPosZ);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.DragonProxy;
import org.dragonet.proxy.data.WorldBorder;
import org.dragonet.proxy.form.CustomForm;
import org.dragonet.proxy.form.components.InputComponent;
import org.dragonet.proxy.form.components.LabelComponent;
Expand Down Expand Up @@ -512,7 +513,18 @@ public void sendMessage(String text, TextPacket.Type type) {
packet.setPlatformChatId("");
packet.setMessage(text);

bedrockSession.sendPacket(packet);
sendPacket(packet);
}

public void sendActionBar(String text, int stayTime) {
SetTitlePacket setTitlePacket = new SetTitlePacket();
setTitlePacket.setType(SetTitlePacket.Type.SET_ACTIONBAR_MESSAGE);
setTitlePacket.setText(text);
setTitlePacket.setFadeInTime(0);
setTitlePacket.setStayTime(stayTime);
setTitlePacket.setFadeOutTime(0);

sendPacket(setTitlePacket);
}

public void sendCreativeInventory() {
Expand Down Expand Up @@ -542,6 +554,9 @@ public void sendGamemode() {

public void onTick() {
//entityCache.getEntities().values().forEach(entity -> entity.onTick(this));
if(worldCache.getWorldBorder() != null) {
worldCache.getWorldBorder().onTick(this);
}
}

public RemoteServer getRemoteServer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import org.dragonet.proxy.data.WorldBorder;
import org.dragonet.proxy.data.stats.StatInfo;
import org.dragonet.proxy.network.session.ProxySession;

Expand All @@ -48,6 +49,9 @@ public class WorldCache implements Cache {
@Setter(value = AccessLevel.NONE)
private boolean showCoordinates = true;

@Setter
private WorldBorder worldBorder;


/**
* Starts or stops the daylight cycle in the current world.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.dragonet.proxy.network.translator.java.world;

import com.github.steveice10.mc.protocol.data.game.world.WorldBorderAction;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerWorldBorderPacket;
import com.nukkitx.math.vector.Vector2f;
import lombok.extern.log4j.Log4j2;
import org.dragonet.proxy.data.WorldBorder;
import org.dragonet.proxy.network.session.ProxySession;
import org.dragonet.proxy.network.translator.misc.PacketTranslator;
import org.dragonet.proxy.util.registry.PacketRegisterInfo;

@Log4j2
@PacketRegisterInfo(packet = ServerWorldBorderPacket.class)
public class PCWorldBorderTranslator extends PacketTranslator<ServerWorldBorderPacket> {

@Override
public void translate(ProxySession session, ServerWorldBorderPacket packet) {
WorldBorder worldBorder = session.getWorldCache().getWorldBorder();

if(packet.getAction() != WorldBorderAction.INITIALIZE && worldBorder == null) {
log.warn("World border (action " + packet.getAction().name() + ") is null");
return;
}

switch(packet.getAction()) {
case INITIALIZE:
// should be getCenterZ()
worldBorder = new WorldBorder(Vector2f.from(packet.getCenterX(), packet.getCenterY()), packet.getRadius(), packet.getOldRadius(), packet.getNewRadius(),
packet.getSpeed(), packet.getWarningTime(), packet.getWarningTime());

session.getWorldCache().setWorldBorder(worldBorder);
break;
case SET_SIZE:
worldBorder.setRadius(packet.getRadius());
break;
case LERP_SIZE:
worldBorder.setOldRadius(packet.getOldRadius());
worldBorder.setNewRadius(packet.getNewRadius());
worldBorder.setSpeed(packet.getSpeed());
break;
case SET_CENTER:
// should be getCenterZ()
worldBorder.setCenter(Vector2f.from(packet.getCenterX(), packet.getCenterY()));
break;
case SET_WARNING_TIME:
worldBorder.setWarningTime(packet.getWarningTime());
return;
case SET_WARNING_BLOCKS:
worldBorder.setWarningBlocks(packet.getWarningBlocks());
return;
}

worldBorder.update();
}
}