WIP mechanical engineering implementation

This commit is contained in:
kuroppoi 2021-05-30 22:58:10 +02:00
parent cab8ebbf55
commit 0e0e036e3b
6 changed files with 127 additions and 0 deletions

View file

@ -0,0 +1,32 @@
package brainwine.gameserver.entity.player;
import brainwine.gameserver.item.Item;
/**
* Simple model for keeping track of the last placed item of a player.
* Mainly used for linking switches to doors, trapdoors etc.
*/
public class Placement {
private final int x;
private final int y;
private final Item item;
public Placement(int x, int y, Item item) {
this.x = x;
this.y = y;
this.item = item;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Item getItem() {
return item;
}
}

View file

@ -3,6 +3,7 @@ package brainwine.gameserver.entity.player;
import java.beans.ConstructorProperties;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -26,6 +27,8 @@ import brainwine.gameserver.entity.EntityType;
import brainwine.gameserver.entity.FacingDirection;
import brainwine.gameserver.item.Item;
import brainwine.gameserver.item.ItemRegistry;
import brainwine.gameserver.item.ItemUseType;
import brainwine.gameserver.item.Layer;
import brainwine.gameserver.item.LootGraphic;
import brainwine.gameserver.loot.Loot;
import brainwine.gameserver.server.Message;
@ -51,6 +54,7 @@ import brainwine.gameserver.server.messages.ZoneStatusMessage;
import brainwine.gameserver.server.pipeline.Connection;
import brainwine.gameserver.server.requests.BlocksIgnoreRequest;
import brainwine.gameserver.server.requests.BlocksRequest;
import brainwine.gameserver.util.MapHelper;
import brainwine.gameserver.util.MathUtils;
import brainwine.gameserver.zone.Chunk;
import brainwine.gameserver.zone.MetaBlock;
@ -103,6 +107,7 @@ public class Player extends Entity implements CommandExecutor {
private final Map<Integer, Long> activeChunks = new HashMap<>();
private final Map<Integer, ConfigurableDialog> dialogs = new HashMap<>();
private String clientVersion;
private Placement lastPlacement;
private Item heldItem = Item.AIR;
private int teleportX;
private int teleportY;
@ -243,6 +248,7 @@ public class Player extends Entity implements CommandExecutor {
*/
public void onDisconnect() {
lastHeartbeat = 0;
lastPlacement = null;
if(zone != null) {
zone.removePlayer(this);
@ -418,6 +424,53 @@ public class Player extends Entity implements CommandExecutor {
return heldItem;
}
public void trackPlacement(int x, int y, Item item) {
if(item.getUses().isEmpty() || !zone.areCoordinatesInBounds(x, y)) {
return;
}
boolean linked = false;
if(lastPlacement != null) {
if(item.hasUse(ItemUseType.SWITCHED) && !item.hasUse(ItemUseType.SWITCH)) {
linked = tryLinkSwitchedItem(x, y, item);
}
}
if(!linked) {
lastPlacement = new Placement(x, y, item);
}
}
private boolean tryLinkSwitchedItem(int x, int y, Item item) {
int pX = lastPlacement.getX();
int pY = lastPlacement.getY();
Item pItem = lastPlacement.getItem();
boolean linked = false;
if(pItem.hasUse(ItemUseType.SWITCH)) {
MetaBlock metaBlock = zone.getMetaBlock(pX, pY);
Map<String, Object> metadata = metaBlock == null ? null : metaBlock.getMetadata();
if(metadata != null) {
MapHelper.appendList(metadata, ">", Arrays.asList(x, y));
if(!(item.getUse(ItemUseType.SWITCHED) instanceof String)) {
int mod = zone.getBlock(pX, pY).getFrontMod();
zone.updateBlock(x, y, Layer.FRONT, item, mod, null, null);
}
linked = true;
if(!pItem.hasUse(ItemUseType.MULTI) || MapHelper.getList(metadata, ">", Collections.emptyList()).size() >= 20) {
lastPlacement = null;
}
}
}
return linked;
}
public double getMiningRange() {
return MathUtils.lerp(3.0, 5.0, (double)getSkillLevel(Skill.MINING) / MAX_SKILL_LEVEL);
}

View file

@ -236,6 +236,10 @@ public class Item {
return false;
}
public Object getUse(ItemUseType type) {
return useConfigs.get(type);
}
public Map<ItemUseType, Object> getUses() {
return useConfigs;
}

View file

@ -12,6 +12,9 @@ public enum ItemUseType {
CHANGE,
FIELDABLE,
FLY,
MULTI,
SWITCH,
SWITCHED,
TELEPORT,
ZONE_TELEPORT,

View file

@ -1,15 +1,22 @@
package brainwine.gameserver.server.requests;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import brainwine.gameserver.entity.player.Player;
import brainwine.gameserver.item.Action;
import brainwine.gameserver.item.Item;
import brainwine.gameserver.item.ItemUseType;
import brainwine.gameserver.item.Layer;
import brainwine.gameserver.item.ModType;
import brainwine.gameserver.server.PlayerRequest;
import brainwine.gameserver.server.messages.BlockChangeMessage;
import brainwine.gameserver.server.messages.InventoryMessage;
import brainwine.gameserver.util.MapHelper;
import brainwine.gameserver.util.MathUtils;
import brainwine.gameserver.zone.Block;
import brainwine.gameserver.zone.MetaBlock;
import brainwine.gameserver.zone.Zone;
public class BlockMineRequest extends PlayerRequest {
@ -36,6 +43,7 @@ public class BlockMineRequest extends PlayerRequest {
}
Block block = zone.getBlock(x, y);
MetaBlock metaBlock = zone.getMetaBlock(x, y);
if(block.getItem(layer) != item) {
fail(player, "Could not find the item you're trying to mine.");
@ -57,6 +65,32 @@ public class BlockMineRequest extends PlayerRequest {
return;
}
if(metaBlock != null) {
Map<String, Object> metadata = metaBlock.getMetadata();
if(!metaBlock.hasOwner() && item.hasUse(ItemUseType.SWITCH)) {
List<List<Integer>> positions = MapHelper.getList(metadata, ">", Collections.emptyList());
for(List<Integer> position : positions) {
Block target = zone.getBlock(position.get(0), position.get(1));
if(target != null) {
Item switchedItem = target.getFrontItem();
if(switchedItem.hasUse(ItemUseType.SWITCHED)) {
fail(player, String.format("This switch cannot be mined before its %s.", switchedItem.getTitle().toLowerCase()));
return;
}
}
}
}
if(item.hasUse(ItemUseType.CONTAINER) && metadata.containsKey("$")) {
fail(player, "Can't mine a container with loot in it.");
return;
}
}
Item inventoryItem = item.getMod() == ModType.DECAY && block.getMod(layer) > 0 ? item.getDecayInventoryItem() : item.getInventoryItem();
zone.updateBlock(x, y, layer, 0, 0, player);

View file

@ -68,6 +68,7 @@ public class BlockPlaceRequest extends PlayerRequest {
zone.updateBlock(x, y, layer, item, mod, player);
player.getInventory().removeItem(item);
player.trackPlacement(x, y, item);
}
private void fail(Player player, String reason) {