diff --git a/pom.xml b/pom.xml index c9527bf..b432e3d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ tech.sbdevelopment VehiclesPlusConverter - 0.2.2 + 0.2.4 jar VehiclesPlusConverter @@ -80,9 +80,9 @@ nl.sbdeveloper VehiclesPlus-v3 - 3.0.1 + 3.0.3 system - ${project.basedir}/src/libs/VehiclesPlus-3.0.1.jar + ${project.basedir}/src/libs/VehiclesPlus-3.0.3.jar diff --git a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/VehiclesPlusConverter.java b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/VehiclesPlusConverter.java index 9602116..683a5c7 100644 --- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/VehiclesPlusConverter.java +++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/VehiclesPlusConverter.java @@ -30,8 +30,8 @@ public final class VehiclesPlusConverter extends JavaPlugin { } Version versionNew = Version.of(Bukkit.getPluginManager().getPlugin("VehiclesPlus").getDescription().getVersion()); - if (versionNew.isOlderThan(Version.of("3.0.2"))) { - Bukkit.getLogger().severe("Your VehiclesPlus v3 plugin is too old! Please update to at least v3.0.2!"); + if (versionNew.isOlderThan(Version.of("3.0.3"))) { + Bukkit.getLogger().severe("Your VehiclesPlus v3 plugin is too old! Please update to at least v3.0.3!"); Bukkit.getPluginManager().disablePlugin(this); return; } diff --git a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/api/ConversionException.java b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/api/ConversionException.java index 92a46c7..592df09 100644 --- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/api/ConversionException.java +++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/api/ConversionException.java @@ -1,9 +1,14 @@ package tech.sbdevelopment.vehiclesplusconverter.api; import java.io.IOException; +import java.util.Set; public class ConversionException extends IOException { - public ConversionException(String before, String filename) { - super(before + " " + filename + ".yml"); + public ConversionException(String explanation, String filename) { + super(explanation + " " + filename + ".yml!"); + } + + public ConversionException(String explanation, String filename, String expected, Set available) { + super(explanation + " " + filename + ".yml! Expected " + expected + ", available: " + String.join(", ", available)); } } diff --git a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java index ec30e7f..ea814eb 100644 --- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java +++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java @@ -23,14 +23,19 @@ import nl.sbdeveloper.vehiclesplus.api.vehicles.settings.impl.*; import nl.sbdeveloper.vehiclesplus.storage.db.exceptions.DataStorageException; import nl.sbdeveloper.vehiclesplus.utils.jackson.ColorList; import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; +import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; import tech.sbdevelopment.vehiclesplusconverter.VehiclesPlusConverter; import tech.sbdevelopment.vehiclesplusconverter.api.ConversionException; -import java.util.List; +import java.io.File; +import java.util.Arrays; import java.util.Map; +import java.util.Optional; import java.util.UUID; +import java.util.logging.Level; import static tech.sbdevelopment.vehiclesplusconverter.utils.MainUtil.*; @@ -73,8 +78,7 @@ public class Converter { try { disablePlugin(VehiclesPlus.getInstance()); disablePlugin(VehiclesPlusConverter.getInstance()); - } catch (Exception e) { - e.printStackTrace(); + } catch (Exception ignored) { } } counter--; @@ -85,13 +89,14 @@ public class Converter { private static void convertRims() { for (Map.Entry entry : VehiclesPlus.getVehicleManager().getRimDesignHashMap().entrySet()) { nl.sbdeveloper.vehiclesplus.api.vehicles.rims.RimDesign rd = new nl.sbdeveloper.vehiclesplus.api.vehicles.rims.RimDesign( - entry.getValue().getName(), + entry.getValue().getName().toLowerCase(), entry.getValue().getSkin(), HolderItemPosition.HEAD, entry.getValue().getPrice() ); nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getRimDesigns().put(entry.getKey(), rd); + rd.save(); VehiclesPlusConverter.getInstance().getLogger().info("Converted rim design: " + rd.getName()); } @@ -106,6 +111,7 @@ public class Converter { ); nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getFuelTypes().put(entry.getKey(), ft); + ft.save(); VehiclesPlusConverter.getInstance().getLogger().info("Converted fuel type: " + ft.getName()); } @@ -115,6 +121,11 @@ public class Converter { VehiclesPlusConverter.getInstance().getLogger().info("Converting vehicle models: " + VehiclesPlusAPI.getVehicleManager().getBaseVehicleMap().values().stream().map(BaseVehicle::getName).reduce((s1, s2) -> s1 + ", " + s2).orElse("")); for (BaseVehicle baseVehicle : VehiclesPlusAPI.getVehicleManager().getBaseVehicleMap().values()) { + if (baseVehicle.getName().startsWith("Example")) { + VehiclesPlusConverter.getInstance().getLogger().info("Skipping example vehicle model: " + baseVehicle.getName()); + continue; + } + try { VehicleModel.Builder vehicleModelBuilder = VehicleModel.builder() .id(baseVehicle.getName()) @@ -137,7 +148,12 @@ public class Converter { turretSeat.getXOffset(), turretSeat.getYOffset(), turretSeat.getZOffset(), - baseVehicle.getPartList().stream().filter(Turret.class::isInstance).findFirst().orElseThrow(() -> new ConversionException("No Turret found while loading TurretSeat in file", baseVehicle.getName())).getUID() + baseVehicle.getPartList() + .stream() + .filter(Turret.class::isInstance) + .findFirst() + .orElseThrow(() -> new ConversionException("No Turret found while loading TurretSeat in file", baseVehicle.getName())) + .getUID() )); } else if (part instanceof Seat) { Seat seat = (Seat) part; @@ -187,15 +203,52 @@ public class Converter { )); } else if (part instanceof Wheel) { Wheel wheel = (Wheel) part; - vehicleModelBuilder = vehicleModelBuilder.part(new nl.sbdeveloper.vehiclesplus.api.vehicles.parts.impl.Wheel( + ItemStack wheelSkin = wheel.getSkinColored(); + + // Try to find an existing rim design with this skin + Optional matchingRimDesign = nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getRimDesigns() + .values() + .stream() + .filter(rd -> compareItems(rd.getSkin(), wheelSkin)) + .findFirst(); + + if (matchingRimDesign.isEmpty()) { + // Create a new rim design since no matching one exists + String newRimDesignName = generateRimName(); + nl.sbdeveloper.vehiclesplus.api.vehicles.rims.RimDesign newRimDesign = new nl.sbdeveloper.vehiclesplus.api.vehicles.rims.RimDesign( + newRimDesignName, + wheelSkin, + HolderItemPosition.HEAD, + 1000 + ); + + // Add the new rim design to the rim designs map + nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getRimDesigns().put(newRimDesignName, newRimDesign); + newRimDesign.save(); + VehiclesPlusConverter.getInstance().getLogger().info("Created new rim design '" + newRimDesignName + "' for wheel skin!"); + + // Create the wheel part with the new rim design + vehicleModelBuilder = vehicleModelBuilder.part(new nl.sbdeveloper.vehiclesplus.api.vehicles.parts.impl.Wheel( wheel.getXOffset(), wheel.getYOffset(), wheel.getZOffset(), - nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getRimDesign(VehiclesPlus.getVehicleManager().getRimDesignHashMap().values().stream().findFirst().orElseThrow(() -> new ConversionException("No RimDesign found while loading Wheel in file", baseVehicle.getName())).getName()).orElseThrow(() -> new ConversionException("No matching RimDesign found while loading Wheel in file", baseVehicle.getName())), + newRimDesign, wheel.getColor(), wheel.getSteering(), wheel.getRotationOffset() - )); + )); + } else { + // Use the existing rim design that matches the skin + vehicleModelBuilder = vehicleModelBuilder.part(new nl.sbdeveloper.vehiclesplus.api.vehicles.parts.impl.Wheel( + wheel.getXOffset(), + wheel.getYOffset(), + wheel.getZOffset(), + matchingRimDesign.get(), + wheel.getColor(), + wheel.getSteering(), + wheel.getRotationOffset() + )); + } } } @@ -275,6 +328,7 @@ public class Converter { VehiclesPlusConverter.getInstance().getLogger().info("Converted vehicle model: " + model.getId()); saveToVehiclesPlus(model, "vehicles/" + model.getTypeId(), model.getId()); + nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getVehicleModels().put(model.getId(), model); } catch (Exception e) { VehiclesPlusConverter.getInstance().getLogger().log(java.util.logging.Level.SEVERE, "Could not convert vehicle model: " + baseVehicle.getName(), e); } @@ -282,40 +336,77 @@ public class Converter { } private static void convertVehicles() { - for (Map.Entry> set : VehiclesPlusAPI.getVehicleManager().getPlayerVehicleHashMap().entrySet()) { - UUID ownerUUID = set.getKey(); - String ownerName = Bukkit.getOfflinePlayer(ownerUUID).getName(); - if (ownerName == null) { - VehiclesPlusConverter.getInstance().getLogger().severe("Could not convert vehicles for player with UUID " + ownerUUID + ", the player name is unknown!"); - continue; - } + File baseDir = new File("plugins/VehiclesPlusPro/data"); + if (!baseDir.exists()) { + VehiclesPlusConverter.getInstance().getLogger().severe("Could not find the VehiclesPlusPro data folder!"); + return; + } - final Garage garage = nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getGarage(ownerName).orElseGet(() -> new Garage(ownerName, ownerUUID)); - VehiclesPlusConverter.getInstance().getLogger().info("Converting vehicles for player with UUID " + ownerUUID + " (" + ownerName + ")..."); + for (File playerDir : baseDir.listFiles()) { + if (playerDir.isDirectory()) { + String ownerUUID = playerDir.getName(); - for (StorageVehicle vehicle : set.getValue()) { - try { - nl.sbdeveloper.vehiclesplus.api.vehicles.impl.StorageVehicle newVehicle = new nl.sbdeveloper.vehiclesplus.api.vehicles.impl.StorageVehicle( - UUID.randomUUID(), - nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getVehicleModels().values().stream().filter(v -> v.getId().equalsIgnoreCase(vehicle.getBaseVehicle())).findFirst().orElseThrow(() -> new ConversionException("No VehicleModel found for", vehicle.getUuid())), - false - ); - - newVehicle.forceSave(); - garage.addVehicle(newVehicle.getUuid()); - } catch (Exception e) { - e.printStackTrace(); - Bukkit.getLogger().severe("Could not convert vehicles for player with UUID " + ownerUUID + ", could not save the vehicle!"); + OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(ownerUUID)); + if (player.getName() == null) { + VehiclesPlusConverter.getInstance().getLogger().severe("Could not find player with UUID: " + ownerUUID + ", skipping..."); + continue; } - VehiclesPlusConverter.getInstance().getLogger().info("Converted vehicle: " + vehicle.getUuid()); - } + VehiclesPlusConverter.getInstance().getLogger().info("Converting vehicles for player with UUID " + ownerUUID + "..."); + final Garage garage = nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getPersonalGarage(player); - try { - garage.forceSave(); - } catch (DataStorageException e) { - e.printStackTrace(); - Bukkit.getLogger().severe("Could not convert vehicles for player with UUID " + ownerUUID + ", could not save the garage!"); + int i = 0; + for (File vehicleFile : playerDir.listFiles()) { + if (vehicleFile.getName().contains(".yml")) { + StorageVehicle vehicle; + try { + vehicle = StorageVehicle.loadFromStorage(vehicleFile.getAbsolutePath()); + } catch (Exception e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not convert vehicles for player with UUID " + ownerUUID + ", could not load the vehicle!", e); + continue; + } + if (vehicle == null) { + Bukkit.getLogger().warning("Failed to load vehicle for player with UUID " + ownerUUID + " from file: " + vehicleFile.getName() + ", skipping..."); + continue; + } + + try { + nl.sbdeveloper.vehiclesplus.api.vehicles.impl.StorageVehicle newVehicle = new nl.sbdeveloper.vehiclesplus.api.vehicles.impl.StorageVehicle( + UUID.randomUUID(), + nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getVehicleModels().values().stream().filter(v -> v.getId().equalsIgnoreCase(vehicle.getBaseVehicle())).findFirst().orElseThrow(() -> new ConversionException("No VehicleModel found for", vehicle.getUuid(), vehicle.getBaseVehicle(), nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getVehicleModels().keySet())), + false + ); + + // Set the vehicle's stats + newVehicle.getStatics().forceSetMaxSpeed(vehicle.getVehicleStats().getSpeed()); + newVehicle.getStatics().forceSetTurningRadius(vehicle.getVehicleStats().getSteering()); + newVehicle.getStatics().forceSetFuelTank(vehicle.getVehicleStats().getFuelTank()); + newVehicle.getStatics().setCurrentFuel(vehicle.getVehicleStats().getCurrentFuel()); + newVehicle.getStatics().forceSetAcceleration(vehicle.getVehicleStats().getAcceleration()); + newVehicle.getStatics().setBroken(vehicle.getVehicleStats().getBroken()); + newVehicle.getStatics().setCurrentHealth(vehicle.getVehicleStats().getHealth()); + + // Set the trunk + newVehicle.getTrunkItems().addAll(Arrays.asList(vehicle.getVehicleTrunk().getContents())); + + newVehicle.forceSave(); + garage.addVehicle(newVehicle.getUuid()); + } catch (Exception e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not convert vehicles for player with UUID " + ownerUUID + ", could not save the vehicle!", e); + } + + VehiclesPlusConverter.getInstance().getLogger().info("Converted vehicle: " + vehicle.getUuid()); + i++; + } + } + + try { + garage.forceSave(); + } catch (DataStorageException e) { + Bukkit.getLogger().log(Level.SEVERE, "Could not convert vehicles for player with UUID " + ownerUUID + ", could not save the garage!", e); + } + + VehiclesPlusConverter.getInstance().getLogger().info("Converted " + i + " vehicles for player with UUID " + ownerUUID); } } } diff --git a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/MainUtil.java b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/MainUtil.java index 921aea4..95b38dc 100644 --- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/MainUtil.java +++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/MainUtil.java @@ -3,6 +3,7 @@ package tech.sbdevelopment.vehiclesplusconverter.utils; import com.google.common.io.Files; import net.md_5.bungee.api.ChatColor; import nl.sbdeveloper.vehiclesplus.storage.file.HJSONFile; +import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import tech.sbdevelopment.vehiclesplusconverter.VehiclesPlusConverter; import tech.sbdevelopment.vehiclesplusconverter.api.ConversionException; @@ -86,4 +87,62 @@ public class MainUtil { VehiclesPlusConverter.getInstance().getLogger().log(Level.SEVERE, "Couldn't save to the file " + fileName, e); } } + + /** + * Compare two ItemStacks for equality based on material type and metadata + * + * @param item1 First ItemStack + * @param item2 Second ItemStack + * @return true if the items are considered equal + */ + public static boolean compareItems(ItemStack item1, ItemStack item2) { + if (item1 == null || item2 == null) return false; + if (!item1.getType().equals(item2.getType())) return false; + + org.bukkit.inventory.meta.ItemMeta meta1 = item1.getItemMeta(); + org.bukkit.inventory.meta.ItemMeta meta2 = item2.getItemMeta(); + + if (meta1 == null || meta2 == null) return meta1 == meta2; + + // Check CustomModelData if available (1.14+) + try { + return meta1.hasCustomModelData() && meta2.hasCustomModelData() + && meta1.getCustomModelData() == meta2.getCustomModelData(); + } catch (NoSuchMethodError ignored) { + // Pre 1.14, check Durability/Damage value instead + return item1.getDurability() == item2.getDurability(); + } + } + + private static final String[] RIM_PREFIXES = { + "sport", "racing", "luxury", "classic", "vintage", "modern", "elite", "premium", "pro", "ultra" + }; + + private static final String[] RIM_TYPES = { + "star", "spoke", "mesh", "alloy", "chrome", "forged", "cast", "split", "blade", "wave" + }; + + private static final String[] RIM_SUFFIXES = { + "design", "series", "line", "edition", "collection", "style", "plus", "max", "elite", "pro" + }; + + /** + * Generate a realistic rim design name + * + * @return A random rim design name + */ + public static String generateRimName() { + String prefix = RIM_PREFIXES[(int) (Math.random() * RIM_PREFIXES.length)]; + String type = RIM_TYPES[(int) (Math.random() * RIM_TYPES.length)]; + String suffix = RIM_SUFFIXES[(int) (Math.random() * RIM_SUFFIXES.length)]; + + // Add a random number between 100 and 999 + int number = 100 + (int) (Math.random() * 900); + + // Convert to PascalCase + return prefix.substring(0, 1).toUpperCase() + prefix.substring(1) + + type.substring(0, 1).toUpperCase() + type.substring(1) + + suffix.substring(0, 1).toUpperCase() + suffix.substring(1) + + number; + } }