Cześć, ostanio zacząłem pisać plugin na silniku serwerowym Spigot. Plugin miał w założeniu działać tak, że mamy menu, wybieramy sobie typ struktury i w miejsu w które patrzymy stawia się najpierw "blueprint", a następnie jak klikniemy stawia się fizyczna struktura. Wszystko udało mi się zaimplementować, ale przy tworzeniu ścian natknąłem się na pewien problem, bo o ile przy fundamencie nie ma znaczenia w którym kierunku go postawimy, bo jest kwadratem, to przy ścianach już się problem pojawił. A mianowicie chodzi tutaj o dopasowywanie struktur do innych struktur. W przypadku fundamentów tego problemu nie ma bo operujemy tylko na dwóch osiach X i Z i mam mechanizm który mi dopasowuje do siatki elementy, ale w osi Y nie mam siatki, a mimo wszystko chciałbym, aby elementy się dopasowywały.
public class GridUtil {
public static Location calculateGridCenter(Location location) {
int coreX = ((location.getBlockX() / 4) * 4) + (location.getBlockX() >= 0 ? 2 : -2);
int coreZ = ((location.getBlockZ() / 4) * 4) + (location.getBlockZ() >= 0 ? 2 : -2);
return new Location(location.getWorld(), coreX, location.getY(), coreZ);
}
}
public class DirectionUtil {
public static Direction yawToDirection(float yaw) {
// return Direction.values()[Math.round(((yaw < 0) ? yaw + 360 : yaw) / 90f) & 0x3];
return Direction.values()[Math.round(((yaw < 0) ? yaw + 360 : yaw) / 90f) % 4];
}
}
public enum SchemaType {
FOUNDATION {
@Override
public void blueprint(BuildSession session, Location lookLocation) {
final Vector[] CORNER_OFFSETS = {
new Vector(-2, 0, -2),
new Vector(-2, 0, 2),
new Vector(2, 0, -2),
new Vector(2, 0, 2)
};
Set<Location> legBlocks = new HashSet<>();
for (Vector offset : CORNER_OFFSETS) {
boolean localHasSolidSupport = false;
Location cornerLocation = lookLocation.clone().add(offset);
for (int i = 1; i <= 4; i++) {
Location legLocation = cornerLocation.clone().subtract(0, i, 0);
Block legBlock = legLocation.getBlock();
if (legBlock.isSolid()) {
if (StructureManager.contains(StructureElementType.FRAME, legLocation)) {
return;
}
localHasSolidSupport = true;
break;
}
legBlocks.add(legLocation);
}
if (!localHasSolidSupport) {
return;
}
}
legBlocks.forEach(loc -> {
BlockDisplay display = (BlockDisplay) loc.getWorld().spawnEntity(loc, EntityType.BLOCK_DISPLAY);
display.setBlock(Material.LIGHT_BLUE_STAINED_GLASS.createBlockData());
session.add(StructureElementType.LEG, display);
});
for (int x = -2; x <= 2; x++) {
for (int z = -2; z <= 2; z++) {
Location location = lookLocation.clone().add(x, 0, z);
Block block = location.getBlock();
boolean isBlockOverlapStructure = StructureManager.contains(StructureElementType.FRAME, block.getLocation());
if (!block.getType().equals(Material.AIR)) {
if (!isBlockOverlapStructure || StructureManager.contains(StructureElementType.LEG, block.getLocation())) {
session.clearBlueprint();
return;
}
}
if (!isBlockOverlapStructure) {
BlockDisplay display = (BlockDisplay) location.getWorld().spawnEntity(location, EntityType.BLOCK_DISPLAY);
display.setBlock(Material.LIGHT_BLUE_STAINED_GLASS.createBlockData());
session.add((Math.abs(x) <= 1 && Math.abs(z) <= 1) ? StructureElementType.CORE : StructureElementType.FRAME, display);
}
}
}
}
},
WALL {
@Override
public void blueprint(BuildSession session, Location lookLocation) {
for (int y = -2; y <= 2; y++) {
for (int x = -2; x <= 2; x++) {
Location loc = lookLocation.clone();
session.getDirection().addOffset(loc, x, y);
if (y == -2) {
if (!StructureManager.contains(StructureElementType.FRAME, loc)) {
session.clearBlueprint();
return;
}
}
BlockDisplay display = (BlockDisplay) loc.getWorld().spawnEntity(loc, EntityType.BLOCK_DISPLAY);
display.setBlock(Material.LIGHT_BLUE_STAINED_GLASS.createBlockData());
session.add((Math.abs(x) <= 1 && Math.abs(y) <= 1) ? StructureElementType.CORE : StructureElementType.FRAME, display);
}
}
}
};
public abstract void blueprint(BuildSession session, Location lookLocation);
}
@Getter
@AllArgsConstructor
public enum Direction {
NORTH {
@Override
public void addOffset(Location loc, int x, int y) {
loc.add(x, y, -2);
}
},
EAST {
@Override
public void addOffset(Location loc, int x, int y) {
loc.add(2, y, x);
}
},
SOUTH {
@Override
public void addOffset(Location loc, int x, int y) {
loc.add(x, y, 2);
}
},
WEST {
@Override
public void addOffset(Location loc, int x, int y) {
loc.add(-2, y, x);
}
};
public abstract void addOffset(Location loc, int x, int y);
}
public class OnPlayerMoveListeners implements Listener {
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
Player player = event.getPlayer();
ItemStack itemInMainHand = player.getInventory().getItemInMainHand();
if (itemInMainHand.getType().equals(Material.BLAZE_ROD)) {
BuildSession session = BuildSessionManager.getSession(player.getUniqueId());
Location lookLocation = GridUtil.calculateGridCenter(getTargetBlock(player, 3).getLocation());
if (session.getLastLocation() == null || !session.getLastLocation().equals(lookLocation)) {
if (session.getSchemaType().equals(SchemaType.WALL)) {
session.setDirection(DirectionUtil.yawToDirection(player.getYaw()));
System.out.println(session.getDirection().name());
}
session.clearBlueprint();
session.setLastLocation(lookLocation);
session.getSchemaType().blueprint(session, lookLocation);
}
} else {
BuildSessionManager.removeSession(player.getUniqueId());
}
}
public Block getTargetBlock(Player player, int range) {
BlockIterator iter = new BlockIterator(player, range);
Block lastBlock = iter.next();
while (iter.hasNext()) {
lastBlock = iter.next();
if (lastBlock.getType() == Material.AIR) {
continue;
}
break;
}
return lastBlock;
}
}
- tutaj jest filmik który przedstawia efekt, który chciałbym uzyskać.
Czy ktoś mógłby mi podrzucić pomysł jak można było by wykonać podobne przyciąganie się elementów do siebie?