Skip to content

Commit

Permalink
Merge pull request #34 from Th3Shadowbroker/fix/day-transition-2
Browse files Browse the repository at this point in the history
### Features
- Implemented the placeholder `%region%` for `chat.messages.regionAlreadyCustomized` which is the message shown when the command `/om customize` is used.
- Implemented the `%ouroborosmines_name_<world>_<region>%` placeholder, which displays a mine's name which can be defined in the region's configuration file. If not defined, the placeholder will fallback to the regions id.
- Implemented new time system.

### Fixes
- Fixed a bug that prevented opening-hours to work correctly if the timezone was set manually.
- Fixed a bug that prevented opening-hours from repeating in the give period.
  • Loading branch information
Th3Shadowbroker authored Jul 23, 2020
2 parents 1564eca + 8bdf4c7 commit cfbdc2d
Show file tree
Hide file tree
Showing 12 changed files with 344 additions and 225 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>dev.th3shadowbroker.spigot</groupId>
<artifactId>OuroborosMines</artifactId>
<version>1.7.0-SNAPSHOT</version>
<version>1.7.1-SNAPSHOT</version>

<properties>
<plugin.name>${project.artifactId}</plugin.name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private void createRegionConfiguration(ProtectedRegion region, Player player) {
new RegionConfiguration(region.getId(), player.getWorld().getName());
player.sendMessage(TemplateMessage.from("chat.messages.regionCustomize").insert("region", region.getId()).colorize().toString());
} else {
player.sendMessage(TemplateMessage.from("chat.messages.regionAlreadyCustomized").colorize().toString());
player.sendMessage(TemplateMessage.from("chat.messages.regionAlreadyCustomized").insert("region", region.getId()).colorize().toString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,57 +53,68 @@ public String onPlaceholderRequest(Player player, String identifier){
String[] fragments = identifier.split("_");
if (fragments.length == 0) return "";

String regionWorld = fragments.length >= 2 ? fragments[1] : null;
String regionId = fragments.length >= 3 ? fragments[2] : null;

switch (fragments[0]) {

// For remaining time
case "oh":
case "opening":
// Abort if there are not enough fragments.
if (fragments.length < 3) return "Invalid placeholder!";

String regionWorld = fragments[1];
String regionId = fragments[2];
if (fragments.length >= 3) {

// Check remaining time based on runnables that match in world and region.
long remainingTime = 0;
List<AnnouncementRunnable> matchingRunnables = OuroborosMines.INSTANCE.getAnnouncementManager().getRunnablesForRegion(regionWorld, regionId);
if (!matchingRunnables.isEmpty()) {

// Get regional configuration
Optional<RegionConfiguration> regionConfiguration = OuroborosMines.INSTANCE.getMaterialManager().getMineableMaterialOverrides().stream().filter(rc -> rc.getWorld().getName().equals(regionWorld) && rc.getRegionId().equals(regionId)).findFirst();
if (regionConfiguration.isPresent()) {

// Mines aren't already opened
if (!regionConfiguration.get().minesAreOpen()) {
// Find closest timer
for (AnnouncementRunnable runnable : matchingRunnables) {
if (remainingTime == 0 || runnable.getRemainingTime() < remainingTime) {
remainingTime = runnable.getRemainingTime();
}
}

// Check remaining time based on runnables that match in world and region.
long remainingTime = 0;
List<AnnouncementRunnable> matchingRunnables = OuroborosMines.INSTANCE.getAnnouncementManager().getRunnablesForRegion(regionWorld, regionId);
if (!matchingRunnables.isEmpty()) {
long h = (remainingTime / 1000 / 60 / 60) % 24;
long m = (remainingTime / 1000 / 60) % 60;
long s = (remainingTime / 1000) % 60;

// Get regional configuration
Optional<RegionConfiguration> regionConfiguration = OuroborosMines.INSTANCE.getMaterialManager().getMineableMaterialOverrides().stream().filter(rc -> rc.getWorld().getName().equals(regionWorld) && rc.getRegionId().equals(regionId)).findFirst();
if (regionConfiguration.isPresent()) {
String result = new TemplateMessage(OuroborosMines.INSTANCE.getConfig().getString("placeholders.openingHours.format", "%h%:%m%:%s%"))
.insert("h", String.format("%02d", h))
.insert("m", String.format("%02d", m))
.insert("s", String.format("%02d", s))
.colorize().toRawString();

// Mines aren't already opened
if (!regionConfiguration.get().minesAreOpen()) {
// Find closest timer
for (AnnouncementRunnable runnable : matchingRunnables) {
if (remainingTime == 0 || runnable.getRemainingTime() < remainingTime) {
remainingTime = runnable.getRemainingTime();
}
return result;
} else {
return TemplateMessage.from("placeholders.openingHours.open").colorize().toRawString();
}

long h = (remainingTime / 1000 / 60 / 60) % 24;
long m = (remainingTime / 1000 / 60) % 60;
long s = (remainingTime / 1000) % 60;

String result = new TemplateMessage(OuroborosMines.INSTANCE.getConfig().getString("placeholders.openingHours.format", "%h%:%m%:%s%"))
.insert("h", String.format("%02d", h))
.insert("m", String.format("%02d", m))
.insert("s", String.format("%02d", s))
.colorize().toRawString();

//@TODO Testing not finished. Remaining cases:
// - Single opening hour (Works!)
//@FIXME The date doesn't get reset even though the runnables are scheduled for a 24h cycle, which leads to negative results.
//@TODO Idea. Add one day when the current date lays in the past!
//@TODO Hand over test build to tester

//return String.format("%02d:%02d:%02d", h , m, s);
return result;
} else {
return TemplateMessage.from("placeholders.openingHours.open").colorize().toRawString();
}
} else {
return "Missing opening hours for " + regionId;
}
} else {
return "Invalid placeholder!";
}

case "name":
case "n":
// Abort if there are not enough fragments.
System.out.println(fragments.length);
if (fragments.length >= 3) {
Optional<RegionConfiguration> regionConfiguration = OuroborosMines.INSTANCE.getMaterialManager().getMineableMaterialOverrides().stream().filter(rc -> rc.getWorld().getName().equals(regionWorld) && rc.getRegionId().equals(regionId)).findFirst();;
if (regionConfiguration.isPresent()) {
return regionConfiguration.get().getConfiguration().getString("name", regionConfiguration.get().getRegionId());
}
} else {
return "Invalid placeholder!";
}

// Not specified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,52 +47,52 @@ private void registerRegionalAnnouncements(RegionConfiguration regionConfigurati
// Opening announcement
if (openingHours.isAnnounceOpening()) {
String openingMessage = TemplateMessage.from("chat.messages.announcements.opening", regionConfiguration.getConfiguration()).colorize().toString();
List<Duration> realtimeRanges = openingHours.getRealtimeRange();
List<OMDuration> realtimeRanges = openingHours.getRealtimeRange();

// Entry missing?
if (!taskMap.containsKey(regionConfiguration)) taskMap.put(regionConfiguration, new ArrayList<>());

long delay;
// Realtime should be used
if (!realtimeRanges.isEmpty()) {
for (Duration realtimeRange : realtimeRanges) {
for (OMDuration realtimeRange : realtimeRanges) {
// Get it ready!
delay = realtimeRange.getTicksUntilStart();
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, Duration.DAY_SECONDS * 20, openingMessage, openingHours.getAnnouncementWorlds()));
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, TimeConstants.REALTIME_DAY_SECONDS * 20, openingMessage, openingHours.getAnnouncementWorlds()));
}
}

// Use game-time (in ticks)
else {
// Get it read! (But with a different time system)
delay = TimeUtils.getDifference(openingHours.getTickRange().getMin(), regionConfiguration.getWorld().getTime());
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, TimeUtils.DAY_END, openingMessage, openingHours.getAnnouncementWorlds()));
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, TimeConstants.INGAME_DAY_TICKS, openingMessage, openingHours.getAnnouncementWorlds()));
}
}

// Closing announcement
if (openingHours.isAnnounceClosing()) {
String closingMessage = TemplateMessage.from("chat.messages.announcements.closing", regionConfiguration.getConfiguration()).colorize().toString();
List<Duration> realtimeRanges = openingHours.getRealtimeRange();
List<OMDuration> realtimeRanges = openingHours.getRealtimeRange();

// Entry missing?
if (!taskMap.containsKey(regionConfiguration)) taskMap.put(regionConfiguration, new ArrayList<>());

long delay;
// Realtime should be used
if (!realtimeRanges.isEmpty()) {
for (Duration realtimeRange : realtimeRanges) {
for (OMDuration realtimeRange : realtimeRanges) {
// Get it ready!
delay = realtimeRange.getTicksUntilEnd();
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, Duration.DAY_SECONDS * 20, closingMessage, openingHours.getAnnouncementWorlds()));
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, TimeConstants.REALTIME_DAY_SECONDS * 20, closingMessage, openingHours.getAnnouncementWorlds()));
}
}

// Use game-time (in ticks)
else {
// Get it read! (But with a different time system)
delay = TimeUtils.getDifference(openingHours.getTickRange().getMax(), regionConfiguration.getWorld().getTime());
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, TimeUtils.DAY_END, closingMessage, openingHours.getAnnouncementWorlds()));
taskMap.get(regionConfiguration).add(AnnouncementRunnable.schedule(delay, TimeConstants.INGAME_DAY_TICKS, closingMessage, openingHours.getAnnouncementWorlds()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void run() {

private void resetExecutionTime() {
Calendar calendar = TimeUtils.getCalendarWithTimezone();
calendar.add(Calendar.SECOND, (int) (period == TimeUtils.DAY_END ? TimeUtils.DAY_END : Duration.DAY_SECONDS));
calendar.add(Calendar.SECOND, (int) (period == TimeConstants.INGAME_DAY_TICKS ? TimeConstants.INGAME_DAY_TICKS / 20 : TimeConstants.REALTIME_DAY_SECONDS));
this.executionTime = calendar.getTime();
}

Expand Down Expand Up @@ -116,26 +116,4 @@ public static AnnouncementRunnable schedule(long delay, long period, String mess
return runnable;
}

@Deprecated
public static AnnouncementRunnable schedule(long delay, long period, String message, String... worlds) {

List<World> parsedWorlds = new ArrayList<>();
List<String> worldList = Arrays.asList(worlds);

worldList.forEach(worldName -> {
Optional<World> world = Optional.ofNullable(Bukkit.getServer().getWorld(worldName));
world.ifPresent(parsedWorlds::add);
});

Calendar timeCalendar = TimeUtils.getCalendarWithTimezone();
timeCalendar.add(Calendar.SECOND, (int) delay / 20);

AnnouncementRunnable runnable = new AnnouncementRunnable(timeCalendar.getTime(), message, parsedWorlds);
BukkitTask task = Bukkit.getServer().getScheduler().runTaskTimer(OuroborosMines.INSTANCE, runnable, delay, period);
runnable.setTask(task);
runnable.setDelay(delay);
runnable.setPeriod(period);
return runnable;
}

}
114 changes: 0 additions & 114 deletions src/main/java/dev/th3shadowbroker/ouroboros/mines/util/Duration.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2020 Jens Fischer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package dev.th3shadowbroker.ouroboros.mines.util;

import dev.th3shadowbroker.ouroboros.mines.OuroborosMines;

import java.time.LocalTime;
import java.time.ZoneId;

public class InstantUtilities {

public static OMDuration durationFromString(String rawDuration) {
String[] splitted = rawDuration.split("-");

String[] minString = new String[2];
String[] maxString = new String[2];

String[] minSplitted = splitted[0].split(":");
String[] maxSplitted = splitted[1].split(":");

minString[0] = minSplitted[0];
minString[1] = minSplitted.length > 1 ? minSplitted[1] : "00";

maxString[0] = maxSplitted[0];
maxString[1] = maxSplitted.length > 1 ? maxSplitted[1] : "00";

LocalTime start = LocalTime.of(Integer.parseInt(minString[0]), Integer.parseInt(minString[1]), 0);
LocalTime end = LocalTime.of(Integer.parseInt(maxString[0]), Integer.parseInt(maxString[1]), 0);

return new OMDuration(start, end);
}

public static ZoneId getTimeZone() {
String timezone = OuroborosMines.INSTANCE != null ? OuroborosMines.INSTANCE.getConfig().getString("timezone", "auto") : "auto";
boolean useSystemTimezone = timezone.equalsIgnoreCase("auto");
return useSystemTimezone ? ZoneId.systemDefault() : ZoneId.of(timezone);
}

}
Loading

0 comments on commit cfbdc2d

Please sign in to comment.