diff --git a/README.md b/README.md
index 4be116c..b6b22aa 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,11 @@
This plugin helps with the conversion of data from VehiclesPlus v2 to v3.
## Usage
-1. Make sure you installed both VehiclesPlus v2 and VehiclesPlus v3.
-2. Download the [latest release](https://github.com/SBDPlugins/VehiclesPlusConverter/releases) of the converter and install it into your `plugins` folder.
-3. Restart your server.
-4. Use the `/vpconvert` command and follow the instructions.
-5. The server will restart. After the restart, the new vehicles will be loaded.
\ No newline at end of file
+0. Make sure VehiclesPlus v2 is still installed. Otherwise install it again, you can find the .jar in the version history.
+1. **Back up your v2 VehiclesPlusPro plugin data folder!**
+1. Download VehiclesPlus v3 and the [latest release](https://git.sbdevelopment.tech/SBDevelopment/VehiclesPlusConverter/releases) of the converter and install it into your `plugins` folder.
+1. (Re)start your server and check your console to make sure both v2 and v3 load correctly.
+1. Execute `/vpconvert` and read the instructions.
+1. The plugin will convert all the data to the v3 data folder and stop the server.
+1. Make sure to remove the .jar files of both VehiclesPlus v2 and VehiclesPlusConverter!
+1. Start your server again and enjoy v3! 😉
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d5af6b7..b432e3d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,14 +6,13 @@
tech.sbdevelopment
VehiclesPlusConverter
- 0.1.3
+ 0.2.4
jar
VehiclesPlusConverter
Conversion plugin for v2 to v3.
- 1.8
UTF-8
sbdevelopment.tech
@@ -23,16 +22,15 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
+ 3.13.0
- 10
- 10
+ 11
org.apache.maven.plugins
maven-shade-plugin
- 3.2.4
+ 3.6.0
package
@@ -69,22 +67,22 @@
org.spigotmc
spigot-api
- 1.19.2-R0.1-SNAPSHOT
+ 1.21.4-R0.1-SNAPSHOT
provided
nl.sbdeveloper
VehiclesPlus-v2
- 2.4.4.1
+ 2.4.7.2
system
- ${project.basedir}/src/libs/VehiclesPlus-2.4.4.1.jar
+ ${project.basedir}/src/libs/VehiclesPlus-2.4.7.2.jar
nl.sbdeveloper
VehiclesPlus-v3
- 3.0.0-SNAPSHOT
+ 3.0.3
system
- ${project.basedir}/src/libs/VehiclesPlus-3.0.0-SNAPSHOT.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 4fbe7b9..683a5c7 100644
--- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/VehiclesPlusConverter.java
+++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/VehiclesPlusConverter.java
@@ -3,6 +3,7 @@ package tech.sbdevelopment.vehiclesplusconverter;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import tech.sbdevelopment.vehiclesplusconverter.cmd.ConverterCMD;
+import tech.sbdevelopment.vehiclesplusconverter.utils.Version;
public final class VehiclesPlusConverter extends JavaPlugin {
private static VehiclesPlusConverter instance;
@@ -21,6 +22,20 @@ public final class VehiclesPlusConverter extends JavaPlugin {
return;
}
+ Version versionOld = Version.of(Bukkit.getPluginManager().getPlugin("VehiclesPlusPro").getDescription().getVersion());
+ if (versionOld.isOlderThan(Version.of("2.4.7.1"))) {
+ Bukkit.getLogger().severe("Your VehiclesPlus v2 plugin is too old! Please update to at least v2.4.7.1!");
+ Bukkit.getPluginManager().disablePlugin(this);
+ return;
+ }
+
+ Version versionNew = Version.of(Bukkit.getPluginManager().getPlugin("VehiclesPlus").getDescription().getVersion());
+ 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;
+ }
+
getCommand("vpconvert").setExecutor(new ConverterCMD());
}
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/cmd/ConverterCMD.java b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/cmd/ConverterCMD.java
index ec42e3b..79f4df1 100644
--- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/cmd/ConverterCMD.java
+++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/cmd/ConverterCMD.java
@@ -21,7 +21,7 @@ public class ConverterCMD implements CommandExecutor {
Converter.convert(sender);
} else {
sender.sendMessage(__("&7[&3&lVehiclesPlusConverter&7] &fPlease use &b/vpconvert confirm &fto start the conversion!"));
- sender.sendMessage(__("&7[&3&lVehiclesPlusConverter&7] &4&lPLEASE NOTE: &cExisting v3 vehicles may be overwritten! &c&lCreate a backup before confirming."));
+ sender.sendMessage(__("&7[&3&lVehiclesPlusConverter&7] &4&lPLEASE NOTE: &cExisting v3 vehicles may be overwritten! &c&lCreate a backup before confirming!!!"));
}
}
return true;
diff --git a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java
index d55cc54..ea814eb 100644
--- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java
+++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/handlers/Converter.java
@@ -23,15 +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.Particle;
+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.*;
@@ -69,6 +73,14 @@ public class Converter {
@Override
public void run() {
sender.sendMessage(__("&7[&3&lVehiclesPlusConverter&7] &f" + (counter == 15 ? "Conversion finished! " : "") + "&bRebooting in &3" + counter + " &bseconds..."));
+ if (counter == 1) {
+ sender.sendMessage(__("&7[&3&lVehiclesPlusConverter&7] &4&lPLEASE NOTE: &cVehiclesPlus v2 and the converter are disabled from now on!"));
+ try {
+ disablePlugin(VehiclesPlus.getInstance());
+ disablePlugin(VehiclesPlusConverter.getInstance());
+ } catch (Exception ignored) {
+ }
+ }
counter--;
}
}.runTaskTimer(VehiclesPlusConverter.getInstance(), 20L, 20L);
@@ -77,12 +89,16 @@ 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());
}
}
@@ -95,15 +111,25 @@ public class Converter {
);
nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getFuelTypes().put(entry.getKey(), ft);
+ ft.save();
+
+ VehiclesPlusConverter.getInstance().getLogger().info("Converted fuel type: " + ft.getName());
}
}
private static void convertVehicleModels() {
+ 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())
- .displayName(baseVehicle.getName())
+ .displayName(idToReadable(baseVehicle.getName()))
.typeId(getTypeIdByClass(baseVehicle.getName(), getClassByFullName(baseVehicle.getVehicleType())))
.availableColors(new ColorList(baseVehicle.getBaseColorList()));
@@ -122,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;
@@ -172,16 +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(),
- HolderItemPosition.HEAD,
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()
+ ));
+ }
}
}
@@ -223,7 +290,7 @@ public class Converter {
baseVehicle.getExhaustSettings().getXOffset(),
baseVehicle.getExhaustSettings().getYOffset(),
baseVehicle.getExhaustSettings().getZOffset(),
- Particle.valueOf(baseVehicle.getExhaustSettings().getParticleName())
+ baseVehicle.getExhaustSettings().getParticleName().get()
))
.exitWhileMoving(baseVehicle.getCanExitWhileMoving())
.price(baseVehicle.getPrice())
@@ -239,11 +306,18 @@ public class Converter {
baseVehicle.getHitbox().getHeight()
))
.realisticSteering(baseVehicle.getSteeringType())
- .permissions(Permissions.builder()
- // this was hardcoded because if a config had no permission it produced a null pointer.
+ .permissions(baseVehicle.getPermissions() != null ?
+ Permissions.builder()
+ .buy(baseVehicle.getPermissions().getBuyPermission())
+ .ride(baseVehicle.getPermissions().getRidePermission())
+ .sitWithoutRidePermission(baseVehicle.getPermissions().getEnterWithoutRidePermission())
+ .adjust("vp.adjust." + baseVehicle.getName())
+ .spawn("vp.spawn." + baseVehicle.getName())
+ .build()
+ : Permissions.builder()
.buy("vp.buy." + baseVehicle.getName())
.ride("vp.ride." + baseVehicle.getName())
- .sitWithoutRidePermission(false)
+ .sitWithoutRidePermission(true)
.adjust("vp.adjust." + baseVehicle.getName())
.spawn("vp.spawn." + baseVehicle.getName())
.build())
@@ -251,47 +325,88 @@ public class Converter {
.gearbox(new Gearbox(true, 10))
.build();
- // Idk why but it was detecting type as "car" and it should be "cars" to work
- if (model.getTypeId().equals("car"))
- model.setTypeId("cars");
+ 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) {
- e.printStackTrace();
+ VehiclesPlusConverter.getInstance().getLogger().log(java.util.logging.Level.SEVERE, "Could not convert vehicle model: " + baseVehicle.getName(), e);
}
}
}
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) {
- Bukkit.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));
+ 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(
- 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()))
- );
-
- 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;
}
- }
- 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!");
+ VehiclesPlusConverter.getInstance().getLogger().info("Converting vehicles for player with UUID " + ownerUUID + "...");
+ final Garage garage = nl.sbdeveloper.vehiclesplus.api.VehiclesPlusAPI.getPersonalGarage(player);
+
+ 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 08814e3..95b38dc 100644
--- a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/MainUtil.java
+++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/MainUtil.java
@@ -1,13 +1,18 @@
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;
import tech.sbdevelopment.vehiclesplusconverter.api.InvalidConversionException;
import java.io.File;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.logging.Level;
public class MainUtil {
@@ -24,6 +29,31 @@ public class MainUtil {
return split[split.length - 1]; //Last position
}
+ public static String idToReadable(String id) {
+ if (id.contains("_")) {
+ // Split on _ and capitalize each part
+ String[] split = id.split("_");
+ StringBuilder builder = new StringBuilder();
+ for (String s : split) {
+ builder.append(s.substring(0, 1).toUpperCase()).append(s.substring(1));
+ builder.append(" ");
+ }
+ return builder.toString().trim();
+ } else {
+ // Capitalize the first letter
+ return id.substring(0, 1).toUpperCase() + id.substring(1);
+ }
+ }
+
+ public static void disablePlugin(JavaPlugin plugin) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, IOException {
+ // Call protected .getFile() method, then rename that file to .jar.old and save
+ Method getFile = JavaPlugin.class.getDeclaredMethod("getFile");
+ getFile.setAccessible(true);
+ File file = (File) getFile.invoke(plugin);
+ File renamedFile = new File(file.getParent(), file.getName() + ".disabled");
+ Files.move(file, renamedFile);
+ }
+
public static String getTypeIdByClass(String baseVehicle, String type) throws ConversionException {
switch (type) {
case "BikeType":
@@ -45,7 +75,10 @@ public class MainUtil {
public static void saveToVehiclesPlus(Object data, String subFolder, String fileName) {
File parentFolders = new File(nl.sbdeveloper.vehiclesplus.VehiclesPlus.getInstance().getDataFolder(), subFolder);
- if (!parentFolders.exists() && !parentFolders.mkdirs()) return;
+ if (!parentFolders.exists() && !parentFolders.mkdirs()) {
+ VehiclesPlusConverter.getInstance().getLogger().log(Level.SEVERE, "Couldn't create the folder " + subFolder);
+ return;
+ }
HJSONFile jsonFile = new HJSONFile(nl.sbdeveloper.vehiclesplus.VehiclesPlus.getInstance(), subFolder + "/" + fileName);
try {
@@ -54,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;
+ }
}
diff --git a/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/Version.java b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/Version.java
new file mode 100644
index 0000000..a75d4e3
--- /dev/null
+++ b/src/main/java/tech/sbdevelopment/vehiclesplusconverter/utils/Version.java
@@ -0,0 +1,98 @@
+package tech.sbdevelopment.vehiclesplusconverter.utils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Version implements Comparable {
+ private static final Pattern VERSION_PATTERN = Pattern.compile(
+ "([0-9*]+)\\.([0-9*]+)(?:\\.([0-9*]+))?(?:\\.([0-9*]+))?(?:-SNAPSHOT)?"
+ );
+
+ private final Integer major;
+ private final Integer minor;
+ private final Integer patch;
+ private final Integer build;
+
+ public static Version of(String version) {
+ return new Version(version);
+ }
+
+ Version(String version) {
+ Matcher matcher = VERSION_PATTERN.matcher(version);
+ if (matcher.matches()) {
+ this.major = parsePart(matcher.group(1));
+ this.minor = parsePart(matcher.group(2));
+ this.patch = matcher.group(3) != null ? parsePart(matcher.group(3)) : null;
+ this.build = matcher.group(4) != null ? parsePart(matcher.group(4)) : null;
+ } else {
+ throw new IllegalArgumentException("Invalid version format: " + version);
+ }
+ }
+
+ private Integer parsePart(String part) {
+ if ("*".equals(part)) {
+ return null; // wildcard
+ } else {
+ return Integer.parseInt(part);
+ }
+ }
+
+ public boolean isNewerThan(Version other) {
+ return compareTo(other) > 0;
+ }
+
+ public boolean isOlderThan(Version other) {
+ return compareTo(other) < 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+
+ Version version = (Version) obj;
+
+ return this.compareTo(version) == 0;
+ }
+
+ @Override
+ public int compareTo(Version other) {
+ int result = comparePart(this.major, other.major);
+ if (result != 0) return result;
+
+ result = comparePart(this.minor, other.minor);
+ if (result != 0) return result;
+
+ result = comparePart(this.patch, other.patch);
+ if (result != 0) return result;
+
+ return comparePart(this.build, other.build);
+ }
+
+ private int comparePart(Integer part1, Integer part2) {
+ if (part1 == null && part2 == null) return 0;
+ if (part1 == null) return -1; // wildcard is less than any number
+ if (part2 == null) return 1; // any number is greater than wildcard
+
+ return Integer.compare(part1, part2);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (major != null ? major.hashCode() : 0);
+ result = 31 * result + (minor != null ? minor.hashCode() : 0);
+ result = 31 * result + (patch != null ? patch.hashCode() : 0);
+ result = 31 * result + (build != null ? build.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(major != null ? major : "*").append('.')
+ .append(minor != null ? minor : "*");
+ if (patch != null || build != null) sb.append('.').append(patch != null ? patch : "*");
+ if (build != null) sb.append('.').append(build);
+ return sb.toString();
+ }
+}