Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing clipping for deleted objects and keeping them deleted #157

Merged
merged 2 commits into from Jan 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions ElvargServer/src/main/java/com/elvarg/game/World.java
Expand Up @@ -57,6 +57,11 @@ public class World {
*/
private static List<GameObject> objects = new LinkedList<>();

/**
* The collection of removed {@link GameObject}s..
*/
private static LinkedHashSet<GameObject> removedObjects = new LinkedHashSet<>();

/**
* The collection of {@link Players}s waiting to be added to the game.
*/
Expand Down Expand Up @@ -267,6 +272,10 @@ public static List<GameObject> getObjects() {
return objects;
}

public static LinkedHashSet<GameObject> getRemovedObjects() {
return removedObjects;
}

public static Queue<Player> getAddPlayerQueue() {
return addPlayerQueue;
}
Expand Down
Expand Up @@ -113,7 +113,7 @@ public void removeClip(int x, int y, int height, int shift) {
if (clips[height] == null) {
clips[height] = new int[64][64];
}
clips[height][x - regionAbsX][y - regionAbsY] = /* 16777215 - shift */0;
clips[height][x - regionAbsX][y - regionAbsY] &= ~shift;
}

/**
Expand Down
Expand Up @@ -83,7 +83,8 @@ public static Optional<Region> getRegion(int regionId) {
/**
* Attempts to get a {@link Region} based on coordinates.
*
* @param regionId
* @param x
* @param y
* @return
*/
public static Optional<Region> getRegion(int x, int y) {
Expand All @@ -102,9 +103,9 @@ public static Optional<Region> getRegion(int x, int y) {
* @param height
* @param type
* @param direction
* @param flag
* @param tall
*/
private static void addClippingForVariableObject(int x, int y, int height, int type, int direction, boolean flag, PrivateArea privateArea) {
private static void addClippingForVariableObject(int x, int y, int height, int type, int direction, boolean tall, PrivateArea privateArea) {
if (type == 0) {
if (direction == 0) {
addClipping(x, y, height, 128, privateArea);
Expand Down Expand Up @@ -152,7 +153,8 @@ private static void addClippingForVariableObject(int x, int y, int height, int t
addClipping(x - 1, y, height, 8, privateArea);
}
}
if (flag) {
if (tall) {
// If an object is tall, it blocks projectiles too
if (type == 0) {
if (direction == 0) {
addClipping(x, y, height, 65536, privateArea);
Expand Down Expand Up @@ -212,104 +214,105 @@ private static void addClippingForVariableObject(int x, int y, int height, int t
* @param height
* @param type
* @param direction
* @param flag
* @param tall
*/
private static void removeClippingForVariableObject(int x, int y, int height, int type, int direction,
boolean flag, PrivateArea privateArea) {
boolean tall, PrivateArea privateArea) {
if (type == 0) {
if (direction == 0) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y, height, 0, privateArea);
removeClipping(x, y, height, 128, privateArea);
removeClipping(x - 1, y, height, 8, privateArea);
} else if (direction == 1) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 2, privateArea);
removeClipping(x, y + 1, height, 32, privateArea);
} else if (direction == 2) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y, height, 0, privateArea);
removeClipping(x, y, height, 8, privateArea);
removeClipping(x + 1, y, height, 128, privateArea);
} else if (direction == 3) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y - 1, height, 0, privateArea);
removeClipping(x, y, height, 32, privateArea);
removeClipping(x, y - 1, height, 2, privateArea);
}
} else if (type == 1 || type == 3) {
if (direction == 0) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y, height, 0, privateArea);
removeClipping(x, y, height, 1, privateArea);
removeClipping(x - 1, y, height, 16, privateArea);
} else if (direction == 1) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 4, privateArea);
removeClipping(x + 1, y + 1, height, 64, privateArea);
} else if (direction == 2) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y - 1, height, 0, privateArea);
removeClipping(x, y, height, 16, privateArea);
removeClipping(x + 1, y - 1, height, 1, privateArea);
} else if (direction == 3) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y - 1, height, 0, privateArea);
removeClipping(x, y, height, 64, privateArea);
removeClipping(x - 1, y - 1, height, 4, privateArea);
}
} else if (type == 2) {
if (direction == 0) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y, height, 0, privateArea);
addClipping(x, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 130, privateArea);
removeClipping(x - 1, y, height, 8, privateArea);
removeClipping(x, y + 1, height, 32, privateArea);
} else if (direction == 1) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y + 1, height, 0, privateArea);
addClipping(x + 1, y, height, 0, privateArea);
removeClipping(x, y, height, 10, privateArea);
removeClipping(x, y + 1, height, 32, privateArea);
removeClipping(x + 1, y, height, 128, privateArea);
} else if (direction == 2) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y, height, 0, privateArea);
addClipping(x, y - 1, height, 0, privateArea);
removeClipping(x, y, height, 40, privateArea);
removeClipping(x + 1, y, height, 128, privateArea);
removeClipping(x, y - 1, height, 2, privateArea);
} else if (direction == 3) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y - 1, height, 0, privateArea);
addClipping(x - 1, y, height, 0, privateArea);
removeClipping(x, y, height, 160, privateArea);
removeClipping(x, y - 1, height, 2, privateArea);
removeClipping(x - 1, y, height, 8, privateArea);
}
}
if (flag) {
if (tall) {
// If an object is tall, it blocks projectiles too
if (type == 0) {
if (direction == 0) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y, height, 0, privateArea);
removeClipping(x, y, height, 65536, privateArea);
removeClipping(x - 1, y, height, 4096, privateArea);
} else if (direction == 1) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 1024, privateArea);
removeClipping(x, y + 1, height, 16384, privateArea);
} else if (direction == 2) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y, height, 0, privateArea);
removeClipping(x, y, height, 4096, privateArea);
removeClipping(x + 1, y, height, 65536, privateArea);
} else if (direction == 3) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y - 1, height, 0, privateArea);
removeClipping(x, y, height, 16384, privateArea);
removeClipping(x, y - 1, height, 1024, privateArea);
}
}
if (type == 1 || type == 3) {
if (direction == 0) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 512, privateArea);
removeClipping(x - 1, y + 1, height, 8192, privateArea);
} else if (direction == 1) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 2048, privateArea);
removeClipping(x + 1, y + 1, height, 32768, privateArea);
} else if (direction == 2) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 8192, privateArea);
removeClipping(x + 1, y + 1, height, 512, privateArea);
} else if (direction == 3) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y - 1, height, 0, privateArea);
removeClipping(x, y, height, 32768, privateArea);
removeClipping(x - 1, y - 1, height, 2048, privateArea);
}
} else if (type == 2) {
if (direction == 0) {
addClipping(x, y, height, 0, privateArea);
addClipping(x - 1, y, height, 0, privateArea);
addClipping(x, y + 1, height, 0, privateArea);
removeClipping(x, y, height, 66560, privateArea);
removeClipping(x - 1, y, height, 4096, privateArea);
removeClipping(x, y + 1, height, 16384, privateArea);
} else if (direction == 1) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y + 1, height, 0, privateArea);
addClipping(x + 1, y, height, 0, privateArea);
removeClipping(x, y, height, 5120, privateArea);
removeClipping(x, y + 1, height, 16384, privateArea);
removeClipping(x + 1, y, height, 65536, privateArea);
} else if (direction == 2) {
addClipping(x, y, height, 0, privateArea);
addClipping(x + 1, y, height, 0, privateArea);
addClipping(x, y - 1, height, 0, privateArea);
removeClipping(x, y, height, 20480, privateArea);
removeClipping(x + 1, y, height, 65536, privateArea);
removeClipping(x, y - 1, height, 1024, privateArea);
} else if (direction == 3) {
addClipping(x, y, height, 0, privateArea);
addClipping(x, y - 1, height, 0, privateArea);
addClipping(x - 1, y, height, 0, privateArea);
removeClipping(x, y, height, 81920, privateArea);
removeClipping(x, y - 1, height, 1024, privateArea);
removeClipping(x - 1, y, height, 4096, privateArea);
}
}
}
Expand Down Expand Up @@ -348,9 +351,14 @@ private static void addClippingForSolidObject(int x, int y, int height, int xLen
* @param flag
*/
private static void removeClippingForSolidObject(int x, int y, int height, int xLength, int yLength, boolean flag, PrivateArea privateArea) {
int clipping = 256;
if (flag) {
clipping += 0x20000;
}

for (int x_ = x; x_ < x + xLength; x_++) {
for (int y_ = y; y_ < y + yLength; y_++) {
addClipping(x_, y_, height, 0, privateArea);
removeClipping(x_, y_, height, clipping, privateArea);
}
}
}
Expand Down Expand Up @@ -459,7 +467,7 @@ public static void removeObjectClipping(GameObject object) {

if (type == 22) {
if (def.hasActions() && def.solid) {
addClipping(x, y, height, 0, object.getPrivateArea());
removeClipping(x, y, height, 0x200000, object.getPrivateArea());
}
} else if (type >= 9) {
if (def.solid) {
Expand Down Expand Up @@ -566,9 +574,7 @@ public static boolean wallsExist(Location location, PrivateArea area) {
/**
* Tells you if this direction is walkable.
*
* @param x the x coordinate.
* @param y the y coordinate.
* @param z the z coordinate.
* @param pos The destination.
* @param direction the direction.
* @return if the direction is walkable.
*/
Expand Down
Expand Up @@ -56,6 +56,7 @@ public final class ObjectDefinition extends ObjectIdentifiers {
public String interactions[];
private short[] originalModelTexture;
private short[] modifiedModelTexture;
public int clipType = 2;


public ObjectDefinition() {
Expand All @@ -72,6 +73,10 @@ public static void dumpNames() throws Exception {
}
writer.close();
}
public boolean isClippedDecoration() {
return isInteractive || clipType == 1 || obstructsGround;
}


public static ObjectDefinition forId(int id) {
if (id > streamIndices.length)
Expand Down Expand Up @@ -282,8 +287,10 @@ void readValues(Buffer buffer) {
} else if (opcode == 15) {
objectSizeY = buffer.readUnsignedByte();
} else if (opcode == 17) {
clipType = 0;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anyones reading this and copying these changes to their server, do not include these opcode changes - they will cause bugs (I had to revert them)

solid = false;
} else if (opcode == 18) {
solid = false;
impenetrable = false;
} else if (opcode == 19) {
isInteractive = (buffer.readUnsignedByte() == 1);
Expand All @@ -299,7 +306,7 @@ void readValues(Buffer buffer) {
animation = -1;
}
} else if (opcode == 27) {
// clipType = 1;
clipType = 1;
} else if (opcode == 28) {
decorDisplacement = buffer.readUnsignedByte();
} else if (opcode == 29) {
Expand Down
@@ -1,10 +1,12 @@
package com.elvarg.game.entity.impl.object;

import com.elvarg.game.World;
import com.elvarg.game.collision.RegionManager;
import com.elvarg.game.entity.impl.player.Player;
import com.elvarg.game.model.Location;

import java.util.Iterator;
import java.util.stream.Stream;

/**
* A simple object manager used to manage {@link GameObject}s which are spawned
Expand All @@ -23,11 +25,8 @@ public class ObjectManager {
* @param player The player whose changing region.
*/
public static void onRegionChange(Player player) {
Iterator<GameObject> iterator = World.getObjects().iterator();
for (; iterator.hasNext(); ) {
GameObject object = iterator.next();
perform(object, OperationType.SPAWN);
}
World.getObjects().forEach((o) -> perform(o, OperationType.SPAWN));
World.getRemovedObjects().stream().forEach((o) -> player.getPacketSender().sendObjectRemoval(o));
}

/**
Expand All @@ -45,6 +44,12 @@ public static void register(GameObject object, boolean playerUpdate) {
iterator.remove();
}
}
Stream<GameObject> matchingObjects = World.getRemovedObjects().stream().filter(o -> o.getType() == object.getType() && o.getLocation().equals(object.getLocation()));
matchingObjects.forEach(removedObject -> {
World.getRemovedObjects().remove(removedObject);
RegionManager.removeObjectClipping(removedObject);
});

World.getObjects().add(object);
if (playerUpdate) {
perform(object, OperationType.SPAWN);
Expand All @@ -58,16 +63,10 @@ public static void register(GameObject object, boolean playerUpdate) {
* @param playerUpdate Should the object removal packet be sent to nearby players?
*/
public static void deregister(GameObject object, boolean playerUpdate) {
Iterator<GameObject> iterator = World.getObjects().iterator();
for (; iterator.hasNext(); ) {
GameObject o = iterator.next();
if (o.equals(object)) {
iterator.remove();
}
}
if (playerUpdate) {
perform(object, OperationType.DESPAWN);
}
World.getObjects().removeIf(o -> o.equals(object));
perform(object, OperationType.DESPAWN);

World.getRemovedObjects().add(object);
}

/**
Expand Down
Expand Up @@ -327,7 +327,7 @@ public Location clone() {

@Override
public String toString() {
return "Position values: [x, y, z] - [" + x + ", " + y + ", " + z + "].";
return "[" + x + ", " + y + ", " + z + "]";
}

@Override
Expand Down
Expand Up @@ -10,9 +10,11 @@ public class SpawnObjectCommand implements Command {

@Override
public void execute(Player player, String command, String[] parts) {
int id = Integer.parseInt(parts[1]);
// player.getPacketSender().sendObject(new GameObject(id, player.getLocation().clone(), 10, 0, player.getPrivateArea()));
ObjectManager.register(new GameObject(id, player.getLocation().clone(), 10, 0, player.getPrivateArea()), true);
int id = Integer.parseInt(parts[1]);
int type = parts.length == 3 ? Integer.parseInt(parts[2]) : 10;
int face = parts.length == 4 ? Integer.parseInt(parts[3]) : 0;
GameObject gameObject = new GameObject(id, player.getLocation().clone(), type, face, player.getPrivateArea());
ObjectManager.register(gameObject, true);
}

@Override
Expand Down
Expand Up @@ -921,6 +921,10 @@ public PacketSender sendObject(GameObject object) {
}

public PacketSender sendObjectRemoval(GameObject object) {
if (object == null) {
return this;
}

sendPosition(object.getLocation());
PacketBuilder out = new PacketBuilder(101);
out.put((object.getType() << 2) + (object.getFace() & 3), ValueType.C);
Expand Down