Arcturus-Community/src/main/java/com/eu/habbo/habbohotel/users/HabboItem.java

560 lines
22 KiB
Java

package com.eu.habbo.habbohotel.users;
import com.eu.habbo.Emulator;
import com.eu.habbo.habbohotel.achievements.Achievement;
import com.eu.habbo.habbohotel.achievements.AchievementManager;
import com.eu.habbo.habbohotel.bots.Bot;
import com.eu.habbo.habbohotel.gameclients.GameClient;
import com.eu.habbo.habbohotel.items.FurnitureType;
import com.eu.habbo.habbohotel.items.IEventTriggers;
import com.eu.habbo.habbohotel.items.Item;
import com.eu.habbo.habbohotel.items.interactions.*;
import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTimer;
import com.eu.habbo.habbohotel.rooms.*;
import com.eu.habbo.habbohotel.wired.WiredEffectType;
import com.eu.habbo.habbohotel.wired.WiredHandler;
import com.eu.habbo.habbohotel.wired.WiredTriggerType;
import com.eu.habbo.messages.ServerMessage;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDanceComposer;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserDataComposer;
import com.eu.habbo.messages.outgoing.users.UpdateUserLookComposer;
import gnu.trove.set.hash.THashSet;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.math3.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public abstract class HabboItem implements Runnable, IEventTriggers {
private static final Logger LOGGER = LoggerFactory.getLogger(HabboItem.class);
private static Class[] TOGGLING_INTERACTIONS = new Class[]{
InteractionGameTimer.class,
InteractionWired.class,
InteractionWiredHighscore.class,
InteractionMultiHeight.class
};
private int id;
private int userId;
private int roomId;
private Item baseItem;
private String wallPosition;
private short x;
private short y;
private double z;
private int rotation;
private String extradata;
private int limitedStack;
private int limitedSells;
private boolean needsUpdate = false;
private boolean needsDelete = false;
private boolean isFromGift = false;
public HabboItem(ResultSet set, Item baseItem) throws SQLException {
this.id = set.getInt("id");
this.userId = set.getInt("user_id");
this.roomId = set.getInt("room_id");
this.baseItem = baseItem;
this.wallPosition = set.getString("wall_pos");
this.x = set.getShort("x");
this.y = set.getShort("y");
this.z = set.getDouble("z");
this.rotation = set.getInt("rot");
this.extradata = set.getString("extra_data").isEmpty() ? "0" : set.getString("extra_data");
String ltdData = set.getString("limited_data");
if (!ltdData.isEmpty()) {
this.limitedStack = Integer.parseInt(set.getString("limited_data").split(":")[0]);
this.limitedSells = Integer.parseInt(set.getString("limited_data").split(":")[1]);
}
}
public HabboItem(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
this.id = id;
this.userId = userId;
this.roomId = 0;
this.baseItem = item;
this.wallPosition = "";
this.x = 0;
this.y = 0;
this.z = 0;
this.rotation = 0;
this.extradata = extradata.isEmpty() ? "0" : extradata;
this.limitedSells = limitedSells;
this.limitedStack = limitedStack;
}
public static RoomTile getSquareInFront(RoomLayout roomLayout, HabboItem item) {
return roomLayout.getTileInFront(roomLayout.getTile(item.getX(), item.getY()), item.getRotation());
}
public void serializeFloorData(ServerMessage serverMessage) {
try {
serverMessage.appendInt(this.getId());
serverMessage.appendInt(this.baseItem.getSpriteId());
serverMessage.appendInt(this.x);
serverMessage.appendInt(this.y);
serverMessage.appendInt(this.getRotation());
serverMessage.appendString(Double.toString(this.z));
serverMessage.appendString((this.getBaseItem().getInteractionType().getType() == InteractionTrophy.class || this.getBaseItem().getInteractionType().getType() == InteractionCrackable.class || this.getBaseItem().getName().toLowerCase().equals("gnome_box")) ? "1.0" : ((this.getBaseItem().allowWalk() || this.getBaseItem().allowSit() && this.roomId != 0) ? Item.getCurrentHeight(this) + "" : ""));
//serverMessage.appendString( ? "1.0" : ((this.getBaseItem().allowWalk() || this.getBaseItem().allowSit() && this.roomId != 0) ? Item.getCurrentHeight(this) : ""));
} catch (Exception e) {
LOGGER.error("Caught exception", e);
}
}
public void serializeExtradata(ServerMessage serverMessage) {
if (this.isLimited()) {
serverMessage.appendInt(this.getLimitedSells());
serverMessage.appendInt(this.getLimitedStack());
}
}
public void serializeWallData(ServerMessage serverMessage) {
serverMessage.appendString(this.getId() + "");
serverMessage.appendInt(this.baseItem.getSpriteId());
serverMessage.appendString(this.wallPosition);
if (this instanceof InteractionPostIt)
serverMessage.appendString(this.extradata.split(" ")[0]);
else
serverMessage.appendString(this.extradata);
serverMessage.appendInt(-1);
serverMessage.appendInt(this.isUsable());
serverMessage.appendInt(this.getUserId());
}
public int getId() {
return this.id;
}
public int getGiftAdjustedId() {
if (this.isFromGift) return -this.id;
return this.id;
}
public int getUserId() {
return this.userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getRoomId() {
return this.roomId;
}
public void setRoomId(int roomId) {
this.roomId = roomId;
}
public Item getBaseItem() {
return this.baseItem;
}
public String getWallPosition() {
return this.wallPosition;
}
public void setWallPosition(String wallPosition) {
this.wallPosition = wallPosition;
}
public short getX() {
return this.x;
}
public void setX(short x) {
this.x = x;
}
public short getY() {
return this.y;
}
public void setY(short y) {
this.y = y;
}
public double getZ() {
return this.z;
}
public void setZ(double z) {
if (z > 9999 || z < -9999) return;
this.z = z;
}
public int getRotation() {
return this.rotation;
}
public void setRotation(int rotation) {
this.rotation = (byte) (rotation % 8);
}
public String getExtradata() {
return this.extradata;
}
public void setExtradata(String extradata) {
this.extradata = extradata;
}
public boolean needsUpdate() {
return this.needsUpdate;
}
public boolean needsDelete() {
return needsDelete;
}
public void needsUpdate(boolean value) {
this.needsUpdate = value;
}
public void needsDelete(boolean value) {
this.needsDelete = value;
}
public boolean isLimited() {
return this.limitedStack > 0;
}
public int getLimitedStack() {
return this.limitedStack;
}
public int getLimitedSells() {
return this.limitedSells;
}
public int getMaximumRotations() { return this.baseItem.getRotations(); }
@Override
public void run() {
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection()) {
if (this.needsDelete) {
this.needsUpdate = false;
this.needsDelete = false;
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM items WHERE id = ?")) {
statement.setInt(1, this.getId());
statement.execute();
}
} else if (this.needsUpdate) {
try (PreparedStatement statement = connection.prepareStatement("UPDATE items SET user_id = ?, room_id = ?, wall_pos = ?, x = ?, y = ?, z = ?, rot = ?, extra_data = ?, limited_data = ? WHERE id = ?")) {
statement.setInt(1, this.userId);
statement.setInt(2, this.roomId);
statement.setString(3, this.wallPosition);
statement.setInt(4, this.x);
statement.setInt(5, this.y);
statement.setDouble(6, Math.max(-9999, Math.min(9999, Math.round(this.z * Math.pow(10, 6)) / Math.pow(10, 6))));
statement.setInt(7, this.rotation);
statement.setString(8, this instanceof InteractionGuildGate ? "" : this.getDatabaseExtraData());
statement.setString(9, this.limitedStack + ":" + this.limitedSells);
statement.setInt(10, this.id);
statement.execute();
} catch (SQLException e) {
LOGGER.error("Caught SQL exception", e);
LOGGER.error("SQLException trying to save HabboItem: " + this.toString());
}
this.needsUpdate = false;
}
} catch (SQLException e) {
LOGGER.error("Caught SQL exception", e);
}
}
public abstract boolean canWalkOn(RoomUnit roomUnit, Room room, Object[] objects);
public abstract boolean isWalkable();
@Override
public void onClick(GameClient client, Room room, Object[] objects) throws Exception {
if (client != null && this.getBaseItem().getType() == FurnitureType.FLOOR) {
if (objects != null && objects.length >= 2) {
if (objects[1] instanceof WiredEffectType) {
return;
}
}
if ((this.getBaseItem().getStateCount() > 1 && !(this instanceof InteractionDice)) || Arrays.asList(HabboItem.TOGGLING_INTERACTIONS).contains(this.getClass()) || (objects != null && objects.length == 1 && objects[0].equals("TOGGLE_OVERRIDE"))) {
WiredHandler.handle(WiredTriggerType.STATE_CHANGED, client.getHabbo().getRoomUnit(), room, new Object[]{this});
}
}
}
@Override
public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
/*if (objects != null && objects.length >= 1 && objects[0] instanceof InteractionWired)
return;*/
WiredHandler.handle(WiredTriggerType.WALKS_ON_FURNI, roomUnit, room, new Object[]{this});
if ((this.getBaseItem().allowSit() || this.getBaseItem().allowLay()) && !roomUnit.getDanceType().equals(DanceType.NONE)) {
roomUnit.setDanceType(DanceType.NONE);
room.sendComposer(new RoomUserDanceComposer(roomUnit).compose());
}
if (!this.getBaseItem().getClothingOnWalk().isEmpty() && roomUnit.getPreviousLocation() != roomUnit.getGoal() && roomUnit.getGoal() == room.getLayout().getTile(this.x, this.y)) {
Habbo habbo = room.getHabbo(roomUnit);
if (habbo != null && habbo.getClient() != null) {
String[] clothingKeys = Arrays.stream(this.getBaseItem().getClothingOnWalk().split("\\.")).map(k -> k.split("-")[0]).toArray(String[]::new);
habbo.getHabboInfo().setLook(String.join(".", Arrays.stream(habbo.getHabboInfo().getLook().split("\\.")).filter(k -> !ArrayUtils.contains(clothingKeys, k.split("-")[0])).toArray(String[]::new)) + "." + this.getBaseItem().getClothingOnWalk());
habbo.getClient().sendResponse(new UpdateUserLookComposer(habbo));
if (habbo.getHabboInfo().getCurrentRoom() != null) {
habbo.getHabboInfo().getCurrentRoom().sendComposer(new RoomUserDataComposer(habbo).compose());
}
}
}
}
@Override
public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
if(objects != null && objects.length > 0) {
WiredHandler.handle(WiredTriggerType.WALKS_OFF_FURNI, roomUnit, room, new Object[]{this});
}
}
public abstract void onWalk(RoomUnit roomUnit, Room room, Object[] objects) throws Exception;
public void onPlace(Room room) {
//TODO: IMPORTANT: MAKE THIS GENERIC. (HOLES, ICE SKATE PATCHES, BLACK HOLE, BUNNY RUN FIELD, FOOTBALL FIELD)
Achievement roomDecoAchievement = Emulator.getGameEnvironment().getAchievementManager().getAchievement("RoomDecoFurniCount");
Habbo owner = room.getHabbo(this.getUserId());
int furniCollecterProgress;
if (owner == null) {
furniCollecterProgress = AchievementManager.getAchievementProgressForHabbo(this.getUserId(), roomDecoAchievement);
} else {
furniCollecterProgress = owner.getHabboStats().getAchievementProgress(roomDecoAchievement);
}
int difference = room.getUserFurniCount(this.getUserId()) - furniCollecterProgress;
if (difference > 0) {
if (owner != null) {
AchievementManager.progressAchievement(owner, roomDecoAchievement, difference);
} else {
AchievementManager.progressAchievement(this.getUserId(), roomDecoAchievement, difference);
}
}
Achievement roomDecoUniqueAchievement = Emulator.getGameEnvironment().getAchievementManager().getAchievement("RoomDecoFurniTypeCount");
int uniqueFurniCollecterProgress;
if (owner == null) {
uniqueFurniCollecterProgress = AchievementManager.getAchievementProgressForHabbo(this.getUserId(), roomDecoUniqueAchievement);
} else {
uniqueFurniCollecterProgress = owner.getHabboStats().getAchievementProgress(roomDecoUniqueAchievement);
}
int uniqueDifference = room.getUserUniqueFurniCount(this.getUserId()) - uniqueFurniCollecterProgress;
if (uniqueDifference > 0) {
if (owner != null) {
AchievementManager.progressAchievement(owner, roomDecoUniqueAchievement, uniqueDifference);
} else {
AchievementManager.progressAchievement(this.getUserId(), roomDecoUniqueAchievement, uniqueDifference);
}
}
}
public void onPickUp(Room room) {
if (this.getBaseItem().getEffectF() > 0 || this.getBaseItem().getEffectM() > 0) {
HabboItem topItem2 = room.getTopItemAt(this.getX(), this.getY(), this);
int nextEffectM = 0;
int nextEffectF = 0;
if(topItem2 != null) {
nextEffectM = topItem2.getBaseItem().getEffectM();
nextEffectF = topItem2.getBaseItem().getEffectF();
}
for (Habbo habbo : room.getHabbosOnItem(this)) {
if (this.getBaseItem().getEffectM() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.M) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) {
room.giveEffect(habbo, nextEffectM, -1);
}
if (this.getBaseItem().getEffectF() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.F) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) {
room.giveEffect(habbo, nextEffectF, -1);
}
}
for (Bot bot : room.getBotsAt(room.getLayout().getTile(this.getX(), this.getY()))) {
if (this.getBaseItem().getEffectM() > 0 && bot.getGender().equals(HabboGender.M) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) {
room.giveEffect(bot.getRoomUnit(), nextEffectM, -1);
}
if (this.getBaseItem().getEffectF() > 0 && bot.getGender().equals(HabboGender.F) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) {
room.giveEffect(bot.getRoomUnit(), nextEffectF, -1);
}
}
}
}
public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) {
if (this.getBaseItem().getEffectF() > 0 || this.getBaseItem().getEffectM() > 0) {
HabboItem topItem2 = room.getTopItemAt(oldLocation.x, oldLocation.y, this);
int nextEffectM = 0;
int nextEffectF = 0;
if(topItem2 != null) {
nextEffectM = topItem2.getBaseItem().getEffectM();
nextEffectF = topItem2.getBaseItem().getEffectF();
}
List<Habbo> oldHabbos = new ArrayList<>();
List<Habbo> newHabbos = new ArrayList<>();
List<Bot> oldBots = new ArrayList<>();
List<Bot> newBots = new ArrayList<>();
for (RoomTile tile : room.getLayout().getTilesAt(oldLocation, this.getBaseItem().getWidth(), this.getBaseItem().getLength(), this.getRotation())) {
oldHabbos.addAll(room.getHabbosAt(tile));
oldBots.addAll(room.getBotsAt(tile));
}
for (RoomTile tile : room.getLayout().getTilesAt(oldLocation, this.getBaseItem().getWidth(), this.getBaseItem().getLength(), this.getRotation())) {
newHabbos.addAll(room.getHabbosAt(tile));
newBots.addAll(room.getBotsAt(tile));
}
oldHabbos.removeAll(newHabbos);
oldBots.removeAll(newBots);
for (Habbo habbo : oldHabbos) {
if (this.getBaseItem().getEffectM() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.M) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) {
room.giveEffect(habbo, nextEffectM, -1);
}
if (this.getBaseItem().getEffectF() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.F) && habbo.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) {
room.giveEffect(habbo, nextEffectF, -1);
}
}
for (Habbo habbo : newHabbos) {
if (this.getBaseItem().getEffectM() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.M) && habbo.getRoomUnit().getEffectId() != this.getBaseItem().getEffectM()) {
room.giveEffect(habbo, this.getBaseItem().getEffectM(), -1);
}
if (this.getBaseItem().getEffectF() > 0 && habbo.getHabboInfo().getGender().equals(HabboGender.F) && habbo.getRoomUnit().getEffectId() != this.getBaseItem().getEffectF()) {
room.giveEffect(habbo, this.getBaseItem().getEffectF(), -1);
}
}
for (Bot bot : oldBots) {
if (this.getBaseItem().getEffectM() > 0 && bot.getGender().equals(HabboGender.M) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectM()) {
room.giveEffect(bot.getRoomUnit(), nextEffectM, -1);
}
if (this.getBaseItem().getEffectF() > 0 && bot.getGender().equals(HabboGender.F) && bot.getRoomUnit().getEffectId() == this.getBaseItem().getEffectF()) {
room.giveEffect(bot.getRoomUnit(), nextEffectF, -1);
}
}
for (Bot bot : newBots) {
if (this.getBaseItem().getEffectM() > 0 && bot.getGender().equals(HabboGender.M) && bot.getRoomUnit().getEffectId() != this.getBaseItem().getEffectM()) {
room.giveEffect(bot.getRoomUnit(), this.getBaseItem().getEffectM(), -1);
}
if (this.getBaseItem().getEffectF() > 0 && bot.getGender().equals(HabboGender.F) && bot.getRoomUnit().getEffectId() != this.getBaseItem().getEffectF()) {
room.giveEffect(bot.getRoomUnit(), this.getBaseItem().getEffectF(), -1);
}
}
}
}
public String getDatabaseExtraData() {
return this.getExtradata();
}
@Override
public String toString() {
return "ID: " + this.id + ", BaseID: " + this.getBaseItem().getId() + ", X: " + this.x + ", Y: " + this.y + ", Z: " + this.z + ", Extradata: " + this.extradata;
}
public boolean allowWiredResetState() {
return false;
}
public boolean isUsable() {
return this.baseItem.getStateCount() > 1;
}
public boolean canStackAt(Room room, List<Pair<RoomTile, THashSet<HabboItem>>> itemsAtLocation) {
return true;
}
public boolean isFromGift() {
return isFromGift;
}
public void setFromGift(boolean fromGift) {
isFromGift = fromGift;
}
public boolean invalidatesToRoomKick() { return false; }
public List<RoomTile> getOccupyingTiles(RoomLayout layout) {
List<RoomTile> tiles = new ArrayList<>();
Rectangle rect = RoomLayout.getRectangle(this.getX(), this.getY(), this.getBaseItem().getWidth(), this.getBaseItem().getLength(), this.getRotation());
for (int i = rect.x; i < rect.x + rect.getWidth(); i++) {
for (int j = rect.y; j < rect.y + rect.getHeight(); j++) {
tiles.add(layout.getTile((short) i, (short) j));
}
}
return tiles;
}
public RoomTile getOverrideGoalTile(RoomUnit unit, Room room, RoomTile tile) {
return tile;
}
public RoomTileState getOverrideTileState(RoomTile tile, Room room) {
return null;
}
public boolean canOverrideTile(RoomUnit unit, Room room, RoomTile tile) {
return false;
}
public Rectangle getRectangle() {
return RoomLayout.getRectangle(
this.getX(),
this.getY(),
this.getBaseItem().getWidth(),
this.getBaseItem().getLength(),
this.getRotation());
}
public Rectangle getRectangle(int marginX, int marginY) {
return RoomLayout.getRectangle(
this.getX() - marginX,
this.getY() - marginY,
this.getBaseItem().getWidth() + (marginX * 2),
this.getBaseItem().getLength() + (marginY * 2),
this.getRotation());
}
}