local geoip, remove maxmind dependency
This commit is contained in:
parent
3abb437c5b
commit
31afa3b10f
20 changed files with 437 additions and 164 deletions
6
TODO.md
6
TODO.md
|
@ -1,3 +1,8 @@
|
||||||
|
Current:
|
||||||
|
- weather forecast https://openweathermap.org/forecast5
|
||||||
|
- multiple conditions
|
||||||
|
- on join event
|
||||||
|
|
||||||
Milestone: yesterday
|
Milestone: yesterday
|
||||||
- fix bugs
|
- fix bugs
|
||||||
|
|
||||||
|
@ -8,6 +13,7 @@ Milestone: 0.5.1
|
||||||
|
|
||||||
Milestone: 0.6.0
|
Milestone: 0.6.0
|
||||||
- account for real sun movement, not just time
|
- account for real sun movement, not just time
|
||||||
|
- release / debug separate versions
|
||||||
|
|
||||||
Milestone: future
|
Milestone: future
|
||||||
- weather simulator (weather is clientside rn and doesnt have things such as lightning or other effects)
|
- weather simulator (weather is clientside rn and doesnt have things such as lightning or other effects)
|
||||||
|
|
14
pom.xml
14
pom.xml
|
@ -2,7 +2,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>pl.minecon724</groupId>
|
<groupId>pl.minecon724</groupId>
|
||||||
<artifactId>realweather</artifactId>
|
<artifactId>realweather</artifactId>
|
||||||
<version>0.5.0.1</version>
|
<version>0.5.1-DEV</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
@ -24,15 +24,9 @@
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>json</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>20231013</version>
|
<version>2.10.1</version>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.maxmind.geoip2</groupId>
|
|
||||||
<artifactId>geoip2</artifactId>
|
|
||||||
<version>4.2.0</version>
|
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
|
@ -1,35 +1,46 @@
|
||||||
package pl.minecon724.realweather;
|
package pl.minecon724.realweather;
|
||||||
|
|
||||||
import com.maxmind.geoip2.WebServiceClient;
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import pl.minecon724.realweather.map.WorldMap;
|
import pl.minecon724.realweather.map.WorldMap;
|
||||||
import pl.minecon724.realweather.realtime.RealTimeCommander;
|
import pl.minecon724.realweather.realtime.RealTimeCommander;
|
||||||
import pl.minecon724.realweather.weather.WeatherCommander;
|
import pl.minecon724.realweather.weather.WeatherCommander;
|
||||||
import pl.minecon724.realweather.weather.exceptions.DisabledException;
|
import pl.minecon724.realweather.weather.exceptions.ModuleDisabledException;
|
||||||
|
|
||||||
public class RW extends JavaPlugin {
|
public class RealWeatherPlugin extends JavaPlugin {
|
||||||
FileConfiguration config;
|
|
||||||
|
|
||||||
WebServiceClient client = null;
|
private final Logger logger = getLogger();
|
||||||
|
|
||||||
|
private FileConfiguration config;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
saveDefaultConfig();
|
saveDefaultConfig();
|
||||||
config = getConfig();
|
config = getConfig();
|
||||||
|
|
||||||
SubLogger.init(
|
SubLogger.init(
|
||||||
getLogger(),
|
logger,
|
||||||
config.getBoolean("logging", false)
|
config.getBoolean("logging", false)
|
||||||
);
|
);
|
||||||
|
|
||||||
WorldMap.init(
|
ConfigurationSection mapConfigurationSection = config.getConfigurationSection("map");
|
||||||
config.getConfigurationSection("map")
|
|
||||||
);
|
try {
|
||||||
|
WorldMap.init(
|
||||||
|
mapConfigurationSection,
|
||||||
|
getDataFolder()
|
||||||
|
);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Unable to initialize WorldMap:");
|
||||||
|
e.printStackTrace();
|
||||||
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
|
}
|
||||||
|
|
||||||
WeatherCommander weatherCommander = new WeatherCommander(this);
|
WeatherCommander weatherCommander = new WeatherCommander(this);
|
||||||
try {
|
try {
|
||||||
|
@ -37,9 +48,10 @@ public class RW extends JavaPlugin {
|
||||||
config.getConfigurationSection("weather")
|
config.getConfigurationSection("weather")
|
||||||
);
|
);
|
||||||
weatherCommander.start();
|
weatherCommander.start();
|
||||||
} catch (DisabledException e) {
|
} catch (ModuleDisabledException e) {
|
||||||
getLogger().info("Weather module disabled");
|
logger.info("Weather is disabled by user");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.severe("Couldn't initialize weather provider:");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
getServer().getPluginManager().disablePlugin(this);
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
}
|
}
|
||||||
|
@ -50,11 +62,9 @@ public class RW extends JavaPlugin {
|
||||||
config.getConfigurationSection("time")
|
config.getConfigurationSection("time")
|
||||||
);
|
);
|
||||||
realTimeCommander.start();
|
realTimeCommander.start();
|
||||||
} catch (DisabledException e) {
|
} catch (ModuleDisabledException e) {
|
||||||
getLogger().info("Time module disabled");
|
logger.info("Time is disabled by user");
|
||||||
}
|
}
|
||||||
|
|
||||||
long end = System.currentTimeMillis();
|
|
||||||
this.getLogger().info( String.format( this.getName() + " enabled! (%s ms)", Long.toString( end-start ) ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,19 +4,35 @@ import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class SubLogger {
|
public class SubLogger {
|
||||||
|
// TODO TODO too many static
|
||||||
private static Logger LOGGER;
|
private static Logger LOGGER;
|
||||||
private static boolean ENABLED;
|
private static boolean ENABLED;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the SubLogger
|
||||||
|
* @param logger parent logger, usually JavaPlugin#getLogger()
|
||||||
|
* @param enabled is logging enabled
|
||||||
|
*/
|
||||||
static void init(Logger logger, boolean enabled) {
|
static void init(Logger logger, boolean enabled) {
|
||||||
LOGGER = logger;
|
LOGGER = logger;
|
||||||
ENABLED = enabled;
|
ENABLED = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a SubLogger instance
|
||||||
|
* @param name name, it will be prefixing messages
|
||||||
|
*/
|
||||||
public SubLogger(String name) {
|
public SubLogger(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a message
|
||||||
|
* @param level
|
||||||
|
* @param format message, formatted like {@link String#format(String, Object...)}
|
||||||
|
* @param args args for formatting
|
||||||
|
*/
|
||||||
public void log(Level level, String format, Object... args) {
|
public void log(Level level, String format, Object... args) {
|
||||||
if (!ENABLED) return;
|
if (!ENABLED) return;
|
||||||
|
|
||||||
|
@ -27,7 +43,45 @@ public class SubLogger {
|
||||||
LOGGER.log(level, String.format("[%s] " + format, combinedArgs));
|
LOGGER.log(level, String.format("[%s] " + format, combinedArgs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log an info message
|
||||||
|
* see {@link SubLogger#log(Level, String, Object...)}
|
||||||
|
* @param format message
|
||||||
|
* @param args args
|
||||||
|
*/
|
||||||
public void info(String format, Object... args) {
|
public void info(String format, Object... args) {
|
||||||
this.log(Level.INFO, format, args);
|
this.log(Level.INFO, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void info(String message) {
|
||||||
|
this.log(Level.INFO, message, new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a severe message
|
||||||
|
* see {@link SubLogger#log(Level, String, Object...)}
|
||||||
|
* @param format message
|
||||||
|
* @param args args
|
||||||
|
*/
|
||||||
|
public void severe(String format, Object... args) {
|
||||||
|
this.log(Level.SEVERE, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void severe(String message) {
|
||||||
|
this.log(Level.SEVERE, message, new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a warning message
|
||||||
|
* see {@link SubLogger#log(Level, String, Object...)}
|
||||||
|
* @param format message
|
||||||
|
* @param args args
|
||||||
|
*/
|
||||||
|
public void warning(String format, Object... args) {
|
||||||
|
this.log(Level.WARNING, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void warning(String message) {
|
||||||
|
this.log(Level.WARNING, message, new Object[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package pl.minecon724.realweather.geoip;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
import pl.minecon724.realweather.SubLogger;
|
||||||
|
|
||||||
|
public class DatabaseDownloader {
|
||||||
|
private SubLogger subLogger = new SubLogger("download");
|
||||||
|
private URL downloadUrl;
|
||||||
|
|
||||||
|
public DatabaseDownloader(URL downloadUrl) {
|
||||||
|
this.downloadUrl = downloadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO verify
|
||||||
|
public void download(File file, boolean ipv6) throws IOException {
|
||||||
|
URL url = new URL(downloadUrl, ipv6 ? "ipv6.geo.gz" : "ipv4.geo.gz");
|
||||||
|
|
||||||
|
URLConnection connection = url.openConnection();
|
||||||
|
connection.connect();
|
||||||
|
InputStream inputStream = connection.getInputStream();
|
||||||
|
ReadableByteChannel readableByteChannel = Channels.newChannel(inputStream);
|
||||||
|
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
file.createNewFile();
|
||||||
|
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||||
|
FileChannel fileChannel = fileOutputStream.getChannel();
|
||||||
|
|
||||||
|
long size = connection.getHeaderFieldLong("Content-Length", 0);
|
||||||
|
long position = 0;
|
||||||
|
|
||||||
|
while (position < size) {
|
||||||
|
position += fileChannel.transferFrom(readableByteChannel, position, 1048576);
|
||||||
|
subLogger.info("%d%%", (int)(1.0 * position / size * 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fileChannel.close();
|
||||||
|
fileOutputStream.close();
|
||||||
|
readableByteChannel.close();
|
||||||
|
inputStream.close(); // ok
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package pl.minecon724.realweather.geoip;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
import com.google.common.primitives.Shorts;
|
||||||
|
|
||||||
|
import pl.minecon724.realweather.map.Coordinates;
|
||||||
|
|
||||||
|
public class GeoIPDatabase {
|
||||||
|
private byte formatVersion;
|
||||||
|
private long timestamp;
|
||||||
|
public HashMap<Integer, Coordinates> entries = new HashMap<>();
|
||||||
|
|
||||||
|
public void read(File file) throws IOException, FileNotFoundException {
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timestamp != 0) {
|
||||||
|
throw new IOException("GeoIPDatabase can only be read once");
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
|
GZIPInputStream gzipInputStream = new GZIPInputStream(fileInputStream);
|
||||||
|
|
||||||
|
formatVersion = (byte) gzipInputStream.read();
|
||||||
|
byte[] bytes = gzipInputStream.readNBytes(2);
|
||||||
|
timestamp = recoverTime(bytes);
|
||||||
|
|
||||||
|
byte[] address;
|
||||||
|
Coordinates coordinates;
|
||||||
|
|
||||||
|
while (true) { // TODO true?
|
||||||
|
System.out.println(gzipInputStream.available());
|
||||||
|
address = gzipInputStream.readNBytes(4);
|
||||||
|
if (address.length == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
coordinates = recoverCoordinates(gzipInputStream.readNBytes(6));
|
||||||
|
|
||||||
|
entries.put(IPUtils.toInt(address), coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
gzipInputStream.close();
|
||||||
|
fileInputStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimestamp() {
|
||||||
|
return new SimpleDateFormat("dd.MM.yyyy HH:mm:ss")
|
||||||
|
.format(new Date(timestamp * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getFormatVersion() {
|
||||||
|
return formatVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2 bytes to 4 bytes wow magic
|
||||||
|
* @param bytes 2 bytes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("null") // TODO better way of this?
|
||||||
|
private long recoverTime(byte[] bytes) {
|
||||||
|
long timestamp = 1704067200; // first second of 2024
|
||||||
|
timestamp += Shorts.fromByteArray(bytes) * 60 * 10;
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoded to Coordinates
|
||||||
|
* @param bytes 3 bytes
|
||||||
|
* @return decoded Coordinates
|
||||||
|
*/
|
||||||
|
private Coordinates recoverCoordinates(byte[] bytes) {
|
||||||
|
int skewedLatitude = Ints.fromBytes(
|
||||||
|
(byte)0, bytes[0], bytes[1], bytes[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
int skewedLongitude = Ints.fromBytes(
|
||||||
|
(byte)0, bytes[3], bytes[4], bytes[5]
|
||||||
|
);
|
||||||
|
|
||||||
|
double latitude = (skewedLatitude - 900000) / 10000.0;
|
||||||
|
double longitude = (skewedLongitude - 1800000) / 10000.0;
|
||||||
|
|
||||||
|
return new Coordinates(latitude, longitude);
|
||||||
|
}
|
||||||
|
}
|
32
src/main/java/pl/minecon724/realweather/geoip/IPUtils.java
Normal file
32
src/main/java/pl/minecon724/realweather/geoip/IPUtils.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package pl.minecon724.realweather.geoip;
|
||||||
|
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
|
||||||
|
public class IPUtils {
|
||||||
|
public static byte[] getSubnetStart(byte[] addressBytes, byte subnet) {
|
||||||
|
int address = toInt(addressBytes);
|
||||||
|
int mask = 0xFFFFFFFF << (32 - subnet);
|
||||||
|
|
||||||
|
return fromInt(address & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
public static int toInt(byte[] address) {
|
||||||
|
return Ints.fromByteArray(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] fromInt(int value) {
|
||||||
|
return Ints.toByteArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(byte[] address) {
|
||||||
|
String s = "";
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
s += Integer.toString(address[i] & 0xFF);
|
||||||
|
if (i < 3) s += ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
package pl.minecon724.realweather.map;
|
package pl.minecon724.realweather.map;
|
||||||
|
|
||||||
import com.maxmind.geoip2.record.Location;
|
|
||||||
|
|
||||||
public class Coordinates {
|
public class Coordinates {
|
||||||
public double latitude, longitude;
|
public double latitude, longitude;
|
||||||
|
|
||||||
|
@ -38,11 +36,4 @@ public class Coordinates {
|
||||||
private static double wrapDouble(double min, double max, double val) {
|
private static double wrapDouble(double min, double max, double val) {
|
||||||
return min + (val - min) % (max - min);
|
return min + (val - min) % (max - min);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Coordinates fromGeoIpLocation(Location location) {
|
|
||||||
return new Coordinates(
|
|
||||||
location.getLatitude(),
|
|
||||||
location.getLongitude()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,48 @@
|
||||||
package pl.minecon724.realweather.map;
|
package pl.minecon724.realweather.map;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.maxmind.geoip2.WebServiceClient;
|
|
||||||
import com.maxmind.geoip2.exception.GeoIp2Exception;
|
|
||||||
|
|
||||||
|
import pl.minecon724.realweather.SubLogger;
|
||||||
|
import pl.minecon724.realweather.geoip.DatabaseDownloader;
|
||||||
|
import pl.minecon724.realweather.geoip.GeoIPDatabase;
|
||||||
|
import pl.minecon724.realweather.geoip.IPUtils;
|
||||||
import pl.minecon724.realweather.map.exceptions.GeoIPException;
|
import pl.minecon724.realweather.map.exceptions.GeoIPException;
|
||||||
|
|
||||||
public class GeoLocator {
|
public class GeoLocator {
|
||||||
private static GeoLocator INSTANCE = null;
|
private static GeoLocator INSTANCE = null;
|
||||||
|
|
||||||
private WebServiceClient client;
|
private SubLogger subLogger = new SubLogger("geolocator");
|
||||||
private Map<InetAddress, Coordinates> cache;
|
private GeoIPDatabase database;
|
||||||
|
private HashMap<InetAddress, Coordinates> cache = new HashMap<>();
|
||||||
|
|
||||||
public static void init(int accountId, String apiKey) {
|
public static void init(File databaseFile, String downloadUrl) throws IOException {
|
||||||
INSTANCE = new GeoLocator(
|
INSTANCE = new GeoLocator(
|
||||||
new WebServiceClient.Builder(accountId, apiKey)
|
new GeoIPDatabase());
|
||||||
.host("geolite.info").build());
|
|
||||||
|
INSTANCE.load(databaseFile, downloadUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeoLocator(WebServiceClient client) {
|
public GeoLocator(GeoIPDatabase database) {
|
||||||
this.client = client;
|
this.database = database;
|
||||||
this.cache = new HashMap<>();
|
}
|
||||||
|
|
||||||
|
public void load(File databaseFile, String downloadUrl) throws IOException {
|
||||||
|
subLogger.info("This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com");
|
||||||
|
|
||||||
|
try {
|
||||||
|
database.read(databaseFile);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
new DatabaseDownloader(new URL(downloadUrl))
|
||||||
|
.download(databaseFile, false);
|
||||||
|
database.read(databaseFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
subLogger.info("Database: %s", INSTANCE.database.getTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,35 +52,37 @@ public class GeoLocator {
|
||||||
* @throws GeoIp2Exception
|
* @throws GeoIp2Exception
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static Coordinates getCoordinates(InetAddress address)
|
public static Coordinates getCoordinates(InetAddress inetAddress)
|
||||||
throws GeoIPException {
|
throws GeoIPException {
|
||||||
|
|
||||||
GeoLocator instance = INSTANCE;
|
Coordinates coordinates = INSTANCE.cache.get(inetAddress);
|
||||||
|
|
||||||
Coordinates coordinates = null;
|
|
||||||
|
|
||||||
coordinates = instance.lookup(address);
|
|
||||||
if (coordinates != null)
|
if (coordinates != null)
|
||||||
return coordinates;
|
return coordinates;
|
||||||
|
|
||||||
try {
|
byte[] address = inetAddress.getAddress();
|
||||||
coordinates = Coordinates.fromGeoIpLocation(
|
byte subnet = 32;
|
||||||
instance.client.city(address).getLocation()
|
|
||||||
|
while (coordinates == null) {
|
||||||
|
if (subnet == 0) {
|
||||||
|
INSTANCE.subLogger.info("Not found :(");
|
||||||
|
coordinates = new Coordinates(0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int query = IPUtils.toInt(address);
|
||||||
|
|
||||||
|
coordinates = INSTANCE.database.entries.get(
|
||||||
|
query
|
||||||
);
|
);
|
||||||
} catch (IOException | GeoIp2Exception e) {
|
|
||||||
throw new GeoIPException(e.getMessage());
|
INSTANCE.subLogger.info("trying %s/%d = %d", IPUtils.toString(address), subnet, query);
|
||||||
|
|
||||||
|
address = IPUtils.getSubnetStart(address, --subnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.store(address, coordinates);
|
INSTANCE.subLogger.info("Done, caching");
|
||||||
|
INSTANCE.cache.put(inetAddress, coordinates);
|
||||||
|
|
||||||
return coordinates;
|
return coordinates;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Coordinates lookup(InetAddress address) {
|
|
||||||
return this.cache.get(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void store(InetAddress address, Coordinates coordinates) {
|
|
||||||
this.cache.put(address, coordinates);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package pl.minecon724.realweather.map;
|
package pl.minecon724.realweather.map;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@ -24,8 +27,8 @@ public class WorldMap {
|
||||||
this.point = point;
|
this.point = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(ConfigurationSection config)
|
public static void init(ConfigurationSection config, File dataFolder)
|
||||||
throws IllegalArgumentException {
|
throws IOException {
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
|
|
||||||
|
@ -45,8 +48,8 @@ public class WorldMap {
|
||||||
|
|
||||||
} else if (type == Type.PLAYER) {
|
} else if (type == Type.PLAYER) {
|
||||||
GeoLocator.init(
|
GeoLocator.init(
|
||||||
config.getInt("player.geolite2_accountId"),
|
dataFolder.toPath().resolve("geoip/ipv4.geo.gz").toFile(),
|
||||||
config.getString("player.geolite2_api_key")
|
config.getString("player.download_url", "https://inferior.network/geoip/")
|
||||||
);
|
);
|
||||||
|
|
||||||
} else if (type == Type.GLOBE) {
|
} else if (type == Type.GLOBE) {
|
||||||
|
|
|
@ -14,11 +14,11 @@ import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
|
||||||
import pl.minecon724.realweather.RW;
|
import pl.minecon724.realweather.RealWeatherPlugin;
|
||||||
import pl.minecon724.realweather.weather.exceptions.DisabledException;
|
import pl.minecon724.realweather.weather.exceptions.ModuleDisabledException;
|
||||||
|
|
||||||
public class RealTimeCommander implements Listener {
|
public class RealTimeCommander implements Listener {
|
||||||
private RW plugin;
|
private RealWeatherPlugin plugin;
|
||||||
|
|
||||||
private List<String> worldNames;
|
private List<String> worldNames;
|
||||||
private double scale;
|
private double scale;
|
||||||
|
@ -31,15 +31,15 @@ public class RealTimeCommander implements Listener {
|
||||||
private RealTimeTask task;
|
private RealTimeTask task;
|
||||||
private PlayerTimeSyncTask playerTimeSyncTask;
|
private PlayerTimeSyncTask playerTimeSyncTask;
|
||||||
|
|
||||||
public RealTimeCommander(RW plugin) {
|
public RealTimeCommander(RealWeatherPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(ConfigurationSection config)
|
public void init(ConfigurationSection config)
|
||||||
throws DisabledException {
|
throws ModuleDisabledException {
|
||||||
|
|
||||||
if (!config.getBoolean("enabled"))
|
if (!config.getBoolean("enabled"))
|
||||||
throw new DisabledException();
|
throw new ModuleDisabledException();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
timezone = ZoneId.of(config.getString("timezone"));
|
timezone = ZoneId.of(config.getString("timezone"));
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package pl.minecon724.realweather.weather;
|
package pl.minecon724.realweather.weather;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -9,7 +8,7 @@ import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
import pl.minecon724.realweather.RW;
|
import pl.minecon724.realweather.RealWeatherPlugin;
|
||||||
import pl.minecon724.realweather.SubLogger;
|
import pl.minecon724.realweather.SubLogger;
|
||||||
import pl.minecon724.realweather.map.Coordinates;
|
import pl.minecon724.realweather.map.Coordinates;
|
||||||
import pl.minecon724.realweather.map.WorldMap;
|
import pl.minecon724.realweather.map.WorldMap;
|
||||||
|
@ -17,13 +16,14 @@ import pl.minecon724.realweather.map.WorldMap.Type;
|
||||||
import pl.minecon724.realweather.map.exceptions.GeoIPException;
|
import pl.minecon724.realweather.map.exceptions.GeoIPException;
|
||||||
import pl.minecon724.realweather.weather.WeatherState.State;
|
import pl.minecon724.realweather.weather.WeatherState.State;
|
||||||
import pl.minecon724.realweather.weather.events.WeatherSyncEvent;
|
import pl.minecon724.realweather.weather.events.WeatherSyncEvent;
|
||||||
|
import pl.minecon724.realweather.weather.exceptions.WeatherProviderException;
|
||||||
import pl.minecon724.realweather.weather.provider.Provider;
|
import pl.minecon724.realweather.weather.provider.Provider;
|
||||||
|
|
||||||
public class GetStateTask extends BukkitRunnable {
|
public class GetStateTask extends BukkitRunnable {
|
||||||
|
|
||||||
private SubLogger subLogger = new SubLogger("weather updater");
|
private SubLogger subLogger = new SubLogger("weather updater");
|
||||||
|
|
||||||
private RW plugin;
|
private RealWeatherPlugin plugin;
|
||||||
private Provider provider;
|
private Provider provider;
|
||||||
private WorldMap worldMap;
|
private WorldMap worldMap;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ public class GetStateTask extends BukkitRunnable {
|
||||||
private PluginManager pluginManager = Bukkit.getPluginManager();
|
private PluginManager pluginManager = Bukkit.getPluginManager();
|
||||||
|
|
||||||
public GetStateTask(
|
public GetStateTask(
|
||||||
RW plugin,
|
RealWeatherPlugin plugin,
|
||||||
Provider provider,
|
Provider provider,
|
||||||
WorldMap worldMap
|
WorldMap worldMap
|
||||||
) {
|
) {
|
||||||
|
@ -92,8 +92,9 @@ public class GetStateTask extends BukkitRunnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (WeatherProviderException e) {
|
||||||
subLogger.info("Error updating: %s", e.getMessage());
|
subLogger.info("Weather provider error");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class WeatherChanger implements Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onWorldLoad(WorldLoadEvent event) {
|
public void onWorldLoad(WorldLoadEvent event) {
|
||||||
World world = event.getWorld();
|
World world = event.getWorld();
|
||||||
subLogger.info("World %s is loading", world.getName());
|
subLogger.info("World %s has been loaded", world.getName());
|
||||||
|
|
||||||
if (worldNames.contains(world.getName())) {
|
if (worldNames.contains(world.getName())) {
|
||||||
worlds.add(world);
|
worlds.add(world);
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
package pl.minecon724.realweather.weather;
|
package pl.minecon724.realweather.weather;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
import pl.minecon724.realweather.RW;
|
import pl.minecon724.realweather.RealWeatherPlugin;
|
||||||
import pl.minecon724.realweather.SubLogger;
|
import pl.minecon724.realweather.SubLogger;
|
||||||
import pl.minecon724.realweather.map.Coordinates;
|
import pl.minecon724.realweather.map.Coordinates;
|
||||||
import pl.minecon724.realweather.map.WorldMap;
|
import pl.minecon724.realweather.map.WorldMap;
|
||||||
import pl.minecon724.realweather.weather.exceptions.DisabledException;
|
import pl.minecon724.realweather.weather.exceptions.ModuleDisabledException;
|
||||||
|
import pl.minecon724.realweather.weather.exceptions.WeatherProviderException;
|
||||||
import pl.minecon724.realweather.weather.provider.Provider;
|
import pl.minecon724.realweather.weather.provider.Provider;
|
||||||
|
|
||||||
public class WeatherCommander {
|
public class WeatherCommander {
|
||||||
private WorldMap worldMap = WorldMap.getInstance();
|
private WorldMap worldMap = WorldMap.getInstance();
|
||||||
private RW plugin;
|
private RealWeatherPlugin plugin;
|
||||||
|
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
private List<String> worldNames;
|
private List<String> worldNames;
|
||||||
|
@ -26,23 +26,23 @@ public class WeatherCommander {
|
||||||
|
|
||||||
private SubLogger subLogger = new SubLogger("weather");
|
private SubLogger subLogger = new SubLogger("weather");
|
||||||
|
|
||||||
public WeatherCommander(RW plugin) {
|
public WeatherCommander(RealWeatherPlugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize weather commander
|
* Initialize weather commander
|
||||||
* @param config "weather" ConfigurationSection
|
* @param config "weather" ConfigurationSection
|
||||||
* @throws DisabledException if disabled in config
|
* @throws ModuleDisabledException if disabled in config
|
||||||
* @throws ProviderException if invalid provider config
|
* @throws ProviderException if invalid provider config
|
||||||
*/
|
*/
|
||||||
public void init(ConfigurationSection config)
|
public void init(ConfigurationSection config)
|
||||||
throws DisabledException, IllegalArgumentException {
|
throws ModuleDisabledException, IllegalArgumentException {
|
||||||
|
|
||||||
enabled = config.getBoolean("enabled");
|
enabled = config.getBoolean("enabled");
|
||||||
|
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
throw new DisabledException();
|
throw new ModuleDisabledException();
|
||||||
|
|
||||||
worldNames = config.getStringList("worlds");
|
worldNames = config.getStringList("worlds");
|
||||||
|
|
||||||
|
@ -59,15 +59,15 @@ public class WeatherCommander {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
provider.request_state(new Coordinates(0, 0));
|
provider.request_state(new Coordinates(0, 0));
|
||||||
} catch (IOException e) {
|
} catch (WeatherProviderException e) {
|
||||||
subLogger.info("Provider test failed, errors may occur", new Object[0]);
|
subLogger.severe("Provider test failed, errors may occur");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getServer().getPluginManager().registerEvents(
|
plugin.getServer().getPluginManager().registerEvents(
|
||||||
new WeatherChanger(worldNames), plugin);
|
new WeatherChanger(worldNames), plugin);
|
||||||
|
|
||||||
subLogger.info("done", new Object[0]);
|
subLogger.info("done");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
package pl.minecon724.realweather.weather.exceptions;
|
package pl.minecon724.realweather.weather.exceptions;
|
||||||
|
|
||||||
public class DisabledException extends Exception {
|
public class ModuleDisabledException extends Exception {
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package pl.minecon724.realweather.weather.exceptions;
|
||||||
|
|
||||||
|
public class WeatherProviderException extends Exception {
|
||||||
|
|
||||||
|
public WeatherProviderException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,19 @@
|
||||||
package pl.minecon724.realweather.weather.provider;
|
package pl.minecon724.realweather.weather.provider;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
import com.google.common.base.Charsets;
|
||||||
import org.json.JSONObject;
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
|
||||||
import pl.minecon724.realweather.map.Coordinates;
|
import pl.minecon724.realweather.map.Coordinates;
|
||||||
import pl.minecon724.realweather.weather.WeatherState.*;
|
import pl.minecon724.realweather.weather.WeatherState.*;
|
||||||
|
import pl.minecon724.realweather.weather.exceptions.WeatherProviderException;
|
||||||
|
|
||||||
public class OpenWeatherMapProvider implements Provider {
|
public class OpenWeatherMapProvider implements Provider {
|
||||||
|
|
||||||
|
@ -24,6 +25,11 @@ public class OpenWeatherMapProvider implements Provider {
|
||||||
this.apiKey = apiKey;
|
this.apiKey = apiKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "OpenWeatherMap";
|
||||||
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
try {
|
try {
|
||||||
endpoint = new URL("https://api.openweathermap.org");
|
endpoint = new URL("https://api.openweathermap.org");
|
||||||
|
@ -32,34 +38,40 @@ public class OpenWeatherMapProvider implements Provider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public State request_state(Coordinates coordinates) throws IOException {
|
public State request_state(Coordinates coordinates) throws WeatherProviderException {
|
||||||
JSONObject json = new JSONObject();
|
JsonObject jsonObject;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
URL url = new URL(
|
URL url = new URL(
|
||||||
endpoint + String.format("/data/2.5/weather?lat=%s&lon=%s&appid=%s",
|
String.format("%s/data/2.5/weather?lat=%f&lon=%f&appid=%s",
|
||||||
Double.toString(coordinates.latitude), Double.toString(coordinates.longitude), apiKey
|
endpoint, coordinates.latitude, coordinates.longitude, apiKey
|
||||||
));
|
));
|
||||||
|
|
||||||
InputStream is = url.openStream();
|
InputStream is = url.openStream();
|
||||||
BufferedReader rd = new BufferedReader( new InputStreamReader(is, Charset.forName("UTF-8")) );
|
BufferedReader rd = new BufferedReader(
|
||||||
StringBuilder sb = new StringBuilder();
|
new InputStreamReader(is, Charsets.UTF_8));
|
||||||
int c;
|
|
||||||
while ((c = rd.read()) != -1) {
|
JsonReader jsonReader = new JsonReader(rd);
|
||||||
sb.append((char) c);
|
jsonObject = new Gson().fromJson(jsonReader, JsonObject.class);
|
||||||
}
|
|
||||||
is.close();
|
|
||||||
json = new JSONObject(sb.toString());
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Couldn't contact openweathermap");
|
e.printStackTrace();
|
||||||
|
throw new WeatherProviderException("Couldn't contact openweathermap");
|
||||||
}
|
}
|
||||||
|
|
||||||
int stateId;
|
int stateId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stateId = json.getJSONArray("weather")
|
stateId = jsonObject.getAsJsonArray("weather")
|
||||||
.getJSONObject(0).getInt("id");
|
.get(0).getAsJsonObject()
|
||||||
} catch (JSONException e) {
|
.get("id").getAsInt();
|
||||||
throw new IOException("Invalid data from openweathermap");
|
/*
|
||||||
|
* org.json comparison:
|
||||||
|
* stateId = json.getJSONArray("weather").getJSONObject(0).getInt("id");
|
||||||
|
* so is it truly worth it? yes see loading jsonobject from inputstream
|
||||||
|
*/
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new WeatherProviderException("Invalid data from openweathermap");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here comes the mess
|
// Here comes the mess
|
||||||
|
@ -67,60 +79,44 @@ public class OpenWeatherMapProvider implements Provider {
|
||||||
ConditionLevel level = ConditionLevel.LIGHT;
|
ConditionLevel level = ConditionLevel.LIGHT;
|
||||||
if (stateId < 300) {
|
if (stateId < 300) {
|
||||||
condition = Condition.THUNDER;
|
condition = Condition.THUNDER;
|
||||||
switch (stateId) {
|
switch (stateId % 10) {
|
||||||
case 200:
|
case 0: // 200, 210, 230
|
||||||
case 210:
|
|
||||||
case 230:
|
|
||||||
level = ConditionLevel.LIGHT;
|
level = ConditionLevel.LIGHT;
|
||||||
break;
|
break;
|
||||||
case 201:
|
case 1: // 201, 211, 221, 231
|
||||||
case 211:
|
|
||||||
case 221:
|
|
||||||
case 231:
|
|
||||||
level = ConditionLevel.MODERATE;
|
level = ConditionLevel.MODERATE;
|
||||||
break;
|
break;
|
||||||
case 202:
|
case 2: // 202, 212, 232
|
||||||
case 212:
|
|
||||||
case 232:
|
|
||||||
level = ConditionLevel.HEAVY;
|
level = ConditionLevel.HEAVY;
|
||||||
}
|
}
|
||||||
} else if (stateId < 400) {
|
} else if (stateId < 400) {
|
||||||
condition = Condition.DRIZZLE;
|
condition = Condition.DRIZZLE;
|
||||||
switch (stateId) {
|
switch (stateId % 10) {
|
||||||
case 300:
|
case 0: // 300, 310
|
||||||
case 310:
|
|
||||||
level = ConditionLevel.LIGHT;
|
level = ConditionLevel.LIGHT;
|
||||||
break;
|
break;
|
||||||
case 301:
|
case 1: // 301, 311, 321
|
||||||
case 311:
|
case 3: // 313
|
||||||
case 313:
|
|
||||||
case 321:
|
|
||||||
level = ConditionLevel.MODERATE;
|
level = ConditionLevel.MODERATE;
|
||||||
break;
|
break;
|
||||||
case 302:
|
case 2: // 302, 312
|
||||||
case 312:
|
case 4: // 314
|
||||||
case 314:
|
|
||||||
level = ConditionLevel.HEAVY;
|
level = ConditionLevel.HEAVY;
|
||||||
}
|
}
|
||||||
} else if (stateId < 600) {
|
} else if (stateId < 600) {
|
||||||
condition = Condition.RAIN;
|
condition = Condition.RAIN;
|
||||||
switch (stateId) {
|
switch (stateId % 10) {
|
||||||
case 500:
|
case 0: // 500, 520
|
||||||
case 520:
|
|
||||||
level = ConditionLevel.LIGHT;
|
level = ConditionLevel.LIGHT;
|
||||||
break;
|
break;
|
||||||
case 501:
|
case 1: // 501, 511, 521, 531
|
||||||
case 511:
|
|
||||||
case 521:
|
|
||||||
case 531:
|
|
||||||
level = ConditionLevel.MODERATE;
|
level = ConditionLevel.MODERATE;
|
||||||
break;
|
break;
|
||||||
case 502:
|
case 2: // 502, 522
|
||||||
case 522:
|
|
||||||
level = ConditionLevel.HEAVY;
|
level = ConditionLevel.HEAVY;
|
||||||
break;
|
break;
|
||||||
case 503:
|
case 3: // 503
|
||||||
case 504:
|
case 4: // 504
|
||||||
level = ConditionLevel.EXTREME;
|
level = ConditionLevel.EXTREME;
|
||||||
}
|
}
|
||||||
} else if (stateId < 700) {
|
} else if (stateId < 700) {
|
||||||
|
@ -165,7 +161,16 @@ public class OpenWeatherMapProvider implements Provider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public State[] request_state(Coordinates[] coordinates) throws WeatherProviderException {
|
||||||
return "OpenWeatherMap";
|
// OpenWeatherMap doesnt support bulk requests
|
||||||
|
|
||||||
|
int length = coordinates.length;
|
||||||
|
State[] states = new State[length];
|
||||||
|
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
states[i] = request_state(coordinates[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return states;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package pl.minecon724.realweather.weather.provider;
|
package pl.minecon724.realweather.weather.provider;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import pl.minecon724.realweather.map.Coordinates;
|
import pl.minecon724.realweather.map.Coordinates;
|
||||||
import pl.minecon724.realweather.weather.WeatherState;
|
import pl.minecon724.realweather.weather.WeatherState.State;
|
||||||
|
import pl.minecon724.realweather.weather.exceptions.WeatherProviderException;
|
||||||
|
|
||||||
public interface Provider {
|
public interface Provider {
|
||||||
public void init();
|
public void init();
|
||||||
public WeatherState.State request_state(Coordinates coordinates) throws IOException;
|
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
|
public State request_state(Coordinates coordinates) throws WeatherProviderException;
|
||||||
|
public State[] request_state(Coordinates[] coordinates) throws WeatherProviderException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,7 @@ map:
|
||||||
longitude: -89.485937
|
longitude: -89.485937
|
||||||
|
|
||||||
player:
|
player:
|
||||||
# Get your own @ https://www.maxmind.com/en/geolite2/signup
|
empty: for now
|
||||||
geolite2_accountId: 710438
|
|
||||||
geolite2_api_key: 'qLeseHp4QNQcqRGn'
|
|
||||||
|
|
||||||
globe:
|
globe:
|
||||||
# Valid latitude range: -90 to 90
|
# Valid latitude range: -90 to 90
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
name: RealWeather
|
name: RealWeather
|
||||||
|
author: Minecon724
|
||||||
|
|
||||||
version: ${project.version}
|
version: ${project.version}
|
||||||
api-version: 1.16
|
api-version: 1.16
|
||||||
|
|
||||||
load: STARTUP
|
load: STARTUP
|
||||||
author: Minecon724
|
main: pl.minecon724.realweather.RealWeatherPlugin
|
||||||
main: pl.minecon724.realweather.RW
|
|
||||||
libraries:
|
libraries:
|
||||||
- org.json:json:20231013
|
- com.google.code.gson:gson:2.10.1
|
||||||
- com.maxmind.geoip2:geoip2:4.2.0
|
|
Loading…
Reference in a new issue