package joshie.harvest.npcs.schedule; import joshie.harvest.api.HFApi; import joshie.harvest.api.buildings.BuildingLocation; import joshie.harvest.api.calendar.Festival; import joshie.harvest.api.calendar.Season; import joshie.harvest.api.calendar.Weekday; import joshie.harvest.api.npc.ISchedule; import joshie.harvest.api.npc.NPCEntity; import joshie.harvest.api.npc.schedule.ScheduleBuilder; import joshie.harvest.api.npc.schedule.ScheduleBuilder.Conditional; import joshie.harvest.api.npc.schedule.ScheduleBuilder.HolidaySchedule; import joshie.harvest.api.npc.schedule.ScheduleBuilder.TimedSchedule; import net.minecraft.entity.EntityLiving; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; public class Schedule implements ISchedule { private final TreeMap<Season, TreeMap<Weekday, TreeMap<Long, BuildingLocation>>> seasonalMap = new TreeMap<>(); private final HashMap<Festival, TreeMap<Long, BuildingLocation>> holidayMap = new HashMap<>(); private final Map<BuildingLocation, Conditional> rules = new HashMap<>(); private final BuildingLocation default_; public Schedule(ScheduleBuilder builder) { this.default_ = builder.default_; for (Entry<BuildingLocation, Conditional> entry: builder.rules.entrySet()) rules.put(entry.getKey(), entry.getValue()); for (TimedSchedule time: builder.timedScheduleList) register(time.season, time.weekday, time.time, time.location); for (HolidaySchedule time: builder.holidayScheduleList) register(time.festival, time.time, time.location); } public void register(Festival festival, long time, BuildingLocation location) { TreeMap<Long, BuildingLocation> hourlyMap = getOrCreateMap(holidayMap, festival); hourlyMap.put(time, location); holidayMap.put(festival, hourlyMap); } private TreeMap<Long, BuildingLocation> getOrCreateMap(HashMap<Festival, TreeMap<Long, BuildingLocation>> holidayMap, Festival festival) { return holidayMap.containsKey(festival) ? holidayMap.get(festival) : new TreeMap<>(); } public void register(Season season, Weekday weekday, long time, BuildingLocation location) { TreeMap<Weekday, TreeMap<Long, BuildingLocation>> weekdayMap = getOrCreateMap(season); TreeMap<Long, BuildingLocation> hourlyMap = getOrCreateMap(weekdayMap, weekday); hourlyMap.put(time, location); weekdayMap.put(weekday, hourlyMap); seasonalMap.put(season, weekdayMap); } private TreeMap<Long, BuildingLocation> getOrCreateMap(TreeMap<Weekday, TreeMap<Long, BuildingLocation>> map, Weekday weekday) { return map.containsKey(weekday) ? map.get(weekday) : new TreeMap<>(); } private TreeMap<Weekday, TreeMap<Long, BuildingLocation>> getOrCreateMap(Season season) { return seasonalMap.containsKey(season) ? seasonalMap.get(season) : new TreeMap<>(); } @Override public BuildingLocation getTarget(World world, NPCEntity entity, Season season, Weekday weekday, long time) { BuildingLocation target = getTarget(world, entity.getAsEntity(), season, weekday, time); Conditional conditional = rules.get(target); return conditional == null || conditional.canDo(world, entity) ? target : default_; } private BuildingLocation getTarget(World world, EntityLiving entity, Season season, Weekday weekday, long time) { if (default_ == null) return null; //Holidays take priority over anything else Festival festival = HFApi.calendar.getFestival(world, new BlockPos(entity)); if (!festival.equals(Festival.NONE) && holidayMap.containsKey(festival)) { BuildingLocation location = getTargetFromMapBasedOnTime(holidayMap.get(festival), time); if (location != null) return location; } //Now we stick to normal schedules Season seasonal = seasonalMap.lowerKey(season) == null ? season: seasonalMap.lowerKey(season); if (seasonalMap.containsKey(seasonal)) { TreeMap<Weekday, TreeMap<Long, BuildingLocation>> weekdayMap = seasonalMap.get(seasonal); Weekday weekly = weekdayMap.lowerKey(weekday) == null ? weekday : weekdayMap.lowerKey(weekday); if (weekdayMap.containsKey(weekly)) { BuildingLocation location = getTargetFromMapBasedOnTime(weekdayMap.get(weekly), time); if (location != null) return location; } } return default_; } @Nullable private BuildingLocation getTargetFromMapBasedOnTime(TreeMap<Long, BuildingLocation> hourlyMap, long time) { long Ttime = hourlyMap.lowerKey(time) == null ? time : hourlyMap.lowerKey(time); if (hourlyMap.containsKey(Ttime)) { BuildingLocation location = hourlyMap.get(Ttime); if (location != null) return location; } return null; } }