Optimization + block collision

This commit is contained in:
Felix Cravic 2020-04-20 18:46:39 +02:00
parent 07a0ba2f54
commit 4c25a61720
10 changed files with 169 additions and 203 deletions

View File

@ -6,10 +6,7 @@ import fr.themode.demo.generator.NoiseTestGenerator;
import fr.themode.minestom.MinecraftServer;
import fr.themode.minestom.benchmark.BenchmarkManager;
import fr.themode.minestom.benchmark.ThreadResult;
import fr.themode.minestom.entity.Entity;
import fr.themode.minestom.entity.EntityCreature;
import fr.themode.minestom.entity.GameMode;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.entity.*;
import fr.themode.minestom.event.*;
import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.inventory.Inventory;
@ -115,10 +112,10 @@ public class PlayerInit {
if (event.getHand() != Player.Hand.MAIN)
return;
for (Player p : player.getInstance().getPlayers()) {
/*for (Player p : player.getInstance().getPlayers()) {
if (p != player)
p.teleport(player.getPosition());
}
}*/
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
chickenCreature.setInstance(player.getInstance());
@ -129,6 +126,17 @@ public class PlayerInit {
event.setCancelled(!player.getInventory().addItemStack(event.getItemStack())); // Cancel event if player does not have enough inventory space
});
player.setEventCallback(ItemDropEvent.class, event -> {
ItemStack droppedItem = event.getItemStack();
ItemEntity itemEntity = new ItemEntity(droppedItem);
itemEntity.setPickupDelay(500);
itemEntity.refreshPosition(player.getPosition().clone().add(0, 1.5f, 0));
itemEntity.setInstance(player.getInstance());
Vector velocity = player.getPosition().clone().getDirection().multiply(6);
itemEntity.setVelocity(velocity, 500);
});
player.setEventCallback(PlayerLoginEvent.class, event -> {
event.setSpawningInstance(instanceContainer);
});

View File

@ -25,27 +25,29 @@ public class BoundingBox {
(getMinZ() <= boundingBox.getMaxZ() && getMaxZ() >= boundingBox.getMinZ());
}
// FIXME: seems to do not work properly
public boolean intersect(BlockPosition blockPosition) {
final float x = 1.6f;
final float y = 1;
final float z = 1.6f;
float minX = blockPosition.getX() - (x / 2) + 0.5f;
float maxX = blockPosition.getX() + (x / 2) + 0.5f;
final float x = blockPosition.getX();
final float y = blockPosition.getY();
final float z = blockPosition.getZ();
float minY = blockPosition.getY();
float maxY = blockPosition.getY() + y;
final float offsetX = 1;
final float offsetZ = 1;
float minZ = blockPosition.getZ() - (z / 2) + 0.5f;
float maxZ = blockPosition.getZ() + (z / 2) + 0.5f;
float minX = x;
float maxX = x + offsetX;
if (getMinX() > maxX) return false;
if (getMaxX() < minX) return false;
if (getMinY() > maxY) return false;
if (getMaxY() < minY) return false;
if (getMinZ() > maxZ) return false;
return !(getMaxZ() < minZ);
float minY = y;
float maxY = y + 0.99999f;
float minZ = z;
float maxZ = z + offsetZ;
boolean checkX = getMinX() < maxX && getMaxX() > minX;
boolean checkY = getMinY() < maxY && getMaxY() > minY;
boolean checkZ = getMinZ() < maxZ && getMaxZ() > minZ;
return checkX && checkY && checkZ;
}
@ -53,18 +55,20 @@ public class BoundingBox {
final float x = 1.6f;
final float y = 1;
final float z = 1.6f;
float minX = blockPosition.getX() - (x / 2) + 0.5f;
float maxX = blockPosition.getX() + (x / 2) + 0.5f;
float minX = blockPosition.getX();
float maxX = blockPosition.getX() +x;
float minY = blockPosition.getY();
float maxY = blockPosition.getY() + y;
float minZ = blockPosition.getZ() - (z / 2) + 0.5f;
float maxZ = blockPosition.getZ() + (z / 2) + 0.5f;
float minZ = blockPosition.getZ();
float maxZ = blockPosition.getZ() +z;
boolean checkX = getMinX() + x / 2 < maxX && getMaxX() - x / 2 > minX;
boolean checkY = getMinY() + y < maxY && getMaxY() + y > minY;
boolean checkZ = getMinZ() + z / 2 < maxZ && getMaxZ() - z / 2 > minZ;
System.out.println("test: "+checkX+" : "+checkY+" : "+checkZ);
return checkX && checkY && checkZ;
}*/
@ -82,6 +86,10 @@ public class BoundingBox {
return new BoundingBox(entity, this.x + x, this.y + y, this.z + z);
}
public BoundingBox contract(float x, float y, float z) {
return new BoundingBox(entity, this.x - x, this.y - y, this.z - z);
}
public float getX() {
return x;
}
@ -103,11 +111,11 @@ public class BoundingBox {
}
public float getMinY() {
return entity.getPosition().getY() - (y / 2);
return entity.getPosition().getY();
}
public float getMaxY() {
return entity.getPosition().getY() + (y / 2);
return entity.getPosition().getY() + y;
}
public float getMinZ() {
@ -120,6 +128,13 @@ public class BoundingBox {
@Override
public String toString() {
return "BoundingBox[" + x + ":" + y + ":" + z + "]";
String result = "BoudingBox";
result += "\n";
result += "[" + getMinX() + " : " + getMaxX() + "]";
result += "\n";
result += "[" + getMinY() + " : " + getMaxY() + "]";
result += "\n";
result += "[" + getMinZ() + " : " + getMaxZ() + "]";
return result;
}
}

View File

@ -232,6 +232,7 @@ public abstract class Entity implements Viewable, DataContainer {
boolean zIntersect = boundingBox.intersect(zBlock);
System.out.println(xIntersect + " : " + yIntersect + " : " + zIntersect);
System.out.println(yBlock);
newX = xAir ? newX : xIntersect ? position.getX() : newX;
newY = yAir ? newY : yIntersect ? position.getY() : newY;
newZ = zAir ? newZ : zIntersect ? position.getZ() : newZ;

View File

@ -14,6 +14,7 @@ import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.instance.block.CustomBlock;
import fr.themode.minestom.inventory.Inventory;
import fr.themode.minestom.inventory.PlayerInventory;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.play.*;
@ -92,7 +93,7 @@ public class Player extends LivingEntity {
this.username = username;
this.playerConnection = playerConnection;
setBoundingBox(0.8f, 1.8f, 0.8f);
setBoundingBox(0.6f, 1.8f, 0.6f);
// Some client update
getPlayerConnection().sendPacket(getPropertiesPacket()); // Send default properties
@ -448,6 +449,12 @@ public class Player extends LivingEntity {
sendUpdateHealthPacket();
}
public boolean dropItem(ItemStack item) {
ItemDropEvent itemDropEvent = new ItemDropEvent(item);
callEvent(ItemDropEvent.class, itemDropEvent);
return !itemDropEvent.isCancelled();
}
public void respawn() {
if (!isDead())
return;

View File

@ -6,9 +6,7 @@ import fr.themode.minestom.inventory.click.InventoryClickLoopHandler;
import fr.themode.minestom.inventory.click.InventoryClickProcessor;
import fr.themode.minestom.inventory.click.InventoryClickResult;
import fr.themode.minestom.inventory.condition.InventoryCondition;
import fr.themode.minestom.inventory.condition.InventoryConditionResult;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.item.StackingRule;
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
import fr.themode.minestom.net.packet.server.play.WindowItemsPacket;
@ -198,107 +196,36 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
ItemStack cursorItem = getCursorItem(player); // Isn't used in the algorithm
ItemStack cursor = getCursorItem(player); // Isn't used in the algorithm
// Start condition
InventoryCondition inventoryCondition = getInventoryCondition();
if (inventoryCondition != null) {
InventoryConditionResult result = new InventoryConditionResult(clicked, cursorItem);
inventoryCondition.accept(player, slot, result);
cursorItem = result.getCursorItem();
clicked = result.getClickedItem();
InventoryClickResult clickResult;
if (result.isCancel()) {
//System.out.println(clicked.getMaterial() + " + " + cursorItem.getMaterial());
if (isInWindow) {
setItemStack(slot, clicked);
setCursorPlayerItem(player, cursorItem);
} else {
playerInventory.setItemStack(slot, offset, clicked);
setCursorPlayerItem(player, cursorItem);
}
// Refresh client window
player.getPlayerConnection().sendPacket(getWindowItemsPacket());
return;
}
if (isInWindow) {
clickResult = clickProcessor.shiftClick(getInventoryCondition(), player, slot, clicked, cursor,
// Player inventory loop
new InventoryClickLoopHandler(0, PlayerInventory.INVENTORY_SIZE, 1,
i -> playerInventory.convertToPacketSlot(i),
index -> playerInventory.getItemStack(index, offset),
(index, itemStack) -> playerInventory.setItemStack(index, offset, itemStack)));
} else {
clickResult = clickProcessor.shiftClick(getInventoryCondition(), player, slot, clicked, cursor,
// Window loop
new InventoryClickLoopHandler(0, itemStacks.length, 1,
i -> i,
index -> itemStacks[index],
(index, itemStack) -> setItemStack(index, itemStack)));
}
// End condition
if (clicked.isAir())
if (clickResult == null)
return;
ItemStack resultClicked = clicked.clone();
boolean filled = false;
if (clickResult.doRefresh())
update();
StackingRule clickedRule = clicked.getStackingRule();
int maxSize = clickedRule.getMaxSize();
if (!isInWindow) {
for (int i = 0; i < itemStacks.length; i++) {
ItemStack item = itemStacks[i];
if (clickedRule.canBeStacked(clicked, item)) {
int amount = item.getAmount();
if (amount == maxSize)
continue;
int totalAmount = resultClicked.getAmount() + amount;
if (!clickedRule.canApply(clicked, totalAmount)) {
item = clickedRule.apply(item, maxSize);
setItemStack(i, item);
resultClicked = clickedRule.apply(resultClicked, totalAmount - maxSize);
filled = false;
continue;
} else {
resultClicked = clickedRule.apply(resultClicked, totalAmount);
setItemStack(i, resultClicked);
playerInventory.setItemStack(slot, offset, ItemStack.AIR_ITEM);
filled = true;
break;
}
} else if (item.isAir()) {
// Switch
setItemStack(i, resultClicked);
playerInventory.setItemStack(slot, offset, ItemStack.AIR_ITEM);
filled = true;
break;
}
}
if (!filled) {
playerInventory.setItemStack(slot, offset, resultClicked);
}
} else {
for (int i = 44; i >= 0; i--) { // Hotbar
ItemStack item = playerInventory.getItemStack(i, offset);
if (clickedRule.canBeStacked(clicked, item)) {
int amount = item.getAmount();
if (amount == maxSize)
continue;
int totalAmount = resultClicked.getAmount() + amount;
if (!clickedRule.canApply(clicked, totalAmount)) {
item = clickedRule.apply(item, maxSize);
playerInventory.setItemStack(i, offset, item);
resultClicked = clickedRule.apply(resultClicked, totalAmount - maxSize);
filled = false;
continue;
} else {
resultClicked = clickedRule.apply(resultClicked, totalAmount);
playerInventory.setItemStack(i, offset, resultClicked);
setItemStack(slot, ItemStack.AIR_ITEM);
filled = true;
break;
}
} else if (item.isAir()) {
// Switch
playerInventory.setItemStack(i, offset, resultClicked);
setItemStack(slot, ItemStack.AIR_ITEM);
filled = true;
break;
}
}
if (!filled) { // Still not filled, inventory is full
setItemStack(slot, resultClicked);
}
}
setCursorPlayerItem(player, clickResult.getCursor());
playerInventory.update();
update();
}
@Override
@ -352,7 +279,6 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
s -> isClickInWindow(s) ? getItemStack(s) : playerInventory.getItemStack(s, offset),
(s, item) -> {
System.out.println("click window:" + isClickInWindow(s));
if (isClickInWindow(s)) {
setItemStack(s, item);
} else {
@ -393,7 +319,6 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
index -> playerInventory.getItemStack(index, offset),
(index, itemStack) -> {
playerInventory.setItemStack(index, offset, itemStack);
System.out.println("try: " + index);
}));
if (clickResult == null)

View File

@ -6,7 +6,6 @@ import fr.themode.minestom.inventory.click.InventoryClickLoopHandler;
import fr.themode.minestom.inventory.click.InventoryClickProcessor;
import fr.themode.minestom.inventory.click.InventoryClickResult;
import fr.themode.minestom.inventory.condition.InventoryCondition;
import fr.themode.minestom.inventory.condition.InventoryConditionResult;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.item.StackingRule;
import fr.themode.minestom.net.packet.server.play.EntityEquipmentPacket;
@ -324,71 +323,22 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
@Override
public void shiftClick(Player player, int slot) {
ItemStack cursor = getCursorItem();
ItemStack clicked = getItemStack(slot, OFFSET);
ItemStack cursorItem = getCursorItem(); // Not used
// Start condition
InventoryCondition inventoryCondition = getInventoryCondition();
if (inventoryCondition != null) {
InventoryConditionResult result = new InventoryConditionResult(clicked, cursorItem);
inventoryCondition.accept(player, slot, result);
InventoryClickResult clickResult = clickProcessor.shiftClick(getInventoryCondition(), player, slot, clicked, cursor,
new InventoryClickLoopHandler(0, items.length, 1,
i -> i < 9 ? i + 9 : i - 9,
index -> items[index],
(index, itemStack) -> setItemStack(index, OFFSET, itemStack)));
cursorItem = result.getCursorItem();
clicked = result.getClickedItem();
if (result.isCancel()) {
setItemStack(slot, OFFSET, clicked);
setCursorItem(cursorItem);
// Refresh client slot
sendSlotRefresh((short) slot, clicked);
return;
}
}
// End condition
if (clicked.isAir())
if (clickResult == null)
return;
StackingRule clickedRule = clicked.getStackingRule();
if (clickResult.doRefresh())
update();
ItemStack resultClicked = clicked.clone();
boolean filled = false;
for (int i = 0; i < items.length; i++) {
int index = i < 9 ? i + 9 : i - 9;
ItemStack item = items[index];
StackingRule itemRule = item.getStackingRule();
if (itemRule.canBeStacked(item, clicked)) {
int amount = item.getAmount();
if (!clickedRule.canApply(clicked, amount + 1))
continue;
int totalAmount = resultClicked.getAmount() + amount;
if (!clickedRule.canApply(clicked, totalAmount)) {
item = itemRule.apply(item, itemRule.getMaxSize());
setItemStack(index, OFFSET, item);
resultClicked = clickedRule.apply(resultClicked, totalAmount - clickedRule.getMaxSize());
filled = false;
continue;
} else {
resultClicked = clickedRule.apply(resultClicked, totalAmount);
setItemStack(index, resultClicked);
item = itemRule.apply(item, 0);
setItemStack(slot, OFFSET, item);
filled = true;
break;
}
} else if (item.isAir()) {
// Switch
setItemStack(index, resultClicked);
setItemStack(slot, OFFSET, ItemStack.AIR_ITEM);
filled = true;
break;
}
}
if (!filled) {
setItemStack(slot, OFFSET, resultClicked);
}
setCursorItem(clickResult.getCursor());
}
@Override

View File

@ -156,6 +156,71 @@ public class InventoryClickProcessor {
return clickResult;
}
public InventoryClickResult shiftClick(InventoryCondition inventoryCondition, Player player, int slot,
ItemStack clicked, ItemStack cursor, InventoryClickLoopHandler... loopHandlers) {
InventoryClickResult clickResult = new InventoryClickResult(clicked, cursor);
if (clickResult.isCancel()) {
return clickResult;
}
if (clicked.isAir())
return null;
StackingRule clickedRule = clicked.getStackingRule();
boolean filled = false;
ItemStack resultClicked = clicked.clone();
for (InventoryClickLoopHandler loopHandler : loopHandlers) {
Function<Integer, Integer> indexModifier = loopHandler.getIndexModifier();
Function<Integer, ItemStack> itemGetter = loopHandler.getItemGetter();
BiConsumer<Integer, ItemStack> itemSetter = loopHandler.getItemSetter();
for (int i = loopHandler.getStart(); i < loopHandler.getEnd(); i += loopHandler.getStep()) {
int index = indexModifier.apply(i);
if (index == slot)
continue;
ItemStack item = itemGetter.apply(index);
StackingRule itemRule = item.getStackingRule();
if (itemRule.canBeStacked(item, clicked)) {
int amount = itemRule.getAmount(item);
if (!clickedRule.canApply(clicked, amount + 1))
continue;
int totalAmount = clickedRule.getAmount(resultClicked) + amount;
if (!clickedRule.canApply(clicked, totalAmount)) {
item = itemRule.apply(item, itemRule.getMaxSize());
itemSetter.accept(index, item);
resultClicked = clickedRule.apply(resultClicked, totalAmount - clickedRule.getMaxSize());
filled = false;
continue;
} else {
resultClicked = clickedRule.apply(resultClicked, totalAmount);
itemSetter.accept(index, resultClicked);
item = itemRule.apply(item, 0);
itemSetter.accept(slot, item);
filled = true;
break;
}
} else if (item.isAir()) {
// Switch
itemSetter.accept(index, resultClicked);
itemSetter.accept(slot, ItemStack.AIR_ITEM);
filled = true;
break;
}
}
if (!filled) {
itemSetter.accept(slot, resultClicked);
}
}
return clickResult;
}
public InventoryClickResult dragging(InventoryCondition inventoryCondition, Player player,
int slot, int button,
ItemStack clicked, ItemStack cursor,

View File

@ -73,6 +73,7 @@ public class BlockPlacementListener {
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
if (!playerBlockPlaceEvent.isCancelled() && canPlace) {
player.sendMessage("PLACE BLOCK");
instance.setBlock(blockPosition, material.getBlock());
//instance.setCustomBlock(blockPosition, "updatable");
if (playerBlockPlaceEvent.doesConsumeBlock()) {
@ -87,9 +88,14 @@ public class BlockPlacementListener {
}
}
} else {
// Refresh chunk
Chunk chunk = instance.getChunkAt(blockPosition);
instance.sendChunkSectionUpdate(chunk, ChunkUtils.getSectionAt(blockPosition.getY()), player);
}
} else {
// Refresh chunk
Chunk chunk = instance.getChunkAt(blockPosition);
instance.sendChunkSectionUpdate(chunk, ChunkUtils.getSectionAt(blockPosition.getY()), player);
}
player.getInventory().refreshSlot(player.getHeldSlot());
}

View File

@ -1,9 +1,7 @@
package fr.themode.minestom.listener;
import fr.themode.minestom.entity.GameMode;
import fr.themode.minestom.entity.ItemEntity;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.event.ItemDropEvent;
import fr.themode.minestom.event.PlayerStartDiggingEvent;
import fr.themode.minestom.event.PlayerSwapItemEvent;
import fr.themode.minestom.instance.Instance;
@ -15,7 +13,6 @@ import fr.themode.minestom.net.packet.server.play.AcknowledgePlayerDiggingPacket
import fr.themode.minestom.net.packet.server.play.EntityEffectPacket;
import fr.themode.minestom.net.packet.server.play.RemoveEntityEffectPacket;
import fr.themode.minestom.utils.BlockPosition;
import fr.themode.minestom.utils.Vector;
public class PlayerDiggingListener {
@ -99,17 +96,9 @@ public class PlayerDiggingListener {
}
private static void dropItem(Player player, ItemStack droppedItem, ItemStack handItem) {
ItemDropEvent itemDropEvent = new ItemDropEvent(droppedItem);
player.callCancellableEvent(ItemDropEvent.class, itemDropEvent, () -> {
if (player.dropItem(droppedItem)) {
player.getInventory().setItemInMainHand(handItem);
ItemEntity itemEntity = new ItemEntity(droppedItem);
itemEntity.setPickupDelay(500);
itemEntity.refreshPosition(player.getPosition().clone().add(0, 1.5f, 0));
itemEntity.setInstance(player.getInstance());
Vector velocity = player.getPosition().clone().getDirection().multiply(6);
itemEntity.setVelocity(velocity, 500);
});
}
}
private static void addEffect(Player player) {

View File

@ -11,9 +11,9 @@ public class BlockPosition {
}
public BlockPosition(float x, float y, float z) {
this.x = (int) x;
this.y = (int) y;
this.z = (int) z;
this.x = (int) (x < 0 ? x - 1 : x);
this.y = (int) (y < 0 ? y - 1 : y);
this.z = (int) (z < 0 ? z - 1 : z);
}
public BlockPosition add(int x, int y, int z) {