Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
</dependency>
</dependencies>
<build>
<extensions>
Expand Down
36 changes: 28 additions & 8 deletions src/main/java/us/camin/regions/Region.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,23 +148,43 @@ public void addCharges(int charges) {
m_charges += charges;
}

/**
* Travel should cost:
* <ul>
* <li>0 XP levels between hubs</li>
* <li>1 XP level if the player is leaving a hub</li>
* <li>A scaling amount of XP for the rest, halved if the destination is a hub.</li>
* </ul>
* @param destination The region the player is traveling to
* @return The amount of XP to deduct from the player
*/
public int getTravelCost(Region destination) {
if (isHub() && destination.isHub()) {
return 0;
} else if (isHub()) {
return 1;
}
int baseCost = getBaseTravelCost(destination);
if (baseCost == 0) {
return baseCost;
}
if (destination.isHub()) {
// Travel *to* a hub is 50% cheaper, before charges applied
baseCost /= 2;
}
return Math.max(1, (int)(baseCost / (Math.min(4, m_charges + 1))));
return Math.max(1, (int)(baseCost / (Math.min(4, charges() + 1))));
}

/**
* Computes the raw cost to teleport between two regions, in XP levels.
*
* NOTE: This computation does not include any discounts for hub-based transit,
* nor does it compute any charge-based discounts.
*
* @param destination The region being traveled to
* @return The base cost in XP levels to travel to the given region without any discounts applied
*/
public int getBaseTravelCost(Region destination) {
if (m_isHub && destination.isHub()) {
// Free travel between hubs
return 0;
} else if (m_isHub) {
// Max cost 1 level for travel *from* a hub
return 1;
}
double distance = teleportLocation().distance(destination.teleportLocation());
double blocksPerXP = 500;
return Math.max(1, (int)(distance / blocksPerXP));
Expand Down
77 changes: 77 additions & 0 deletions src/test/java/us/camin/regions/RegionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package us.camin.regions;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;

import org.bukkit.World;
import org.junit.Test;
import org.mockito.Mockito;

import us.camin.regions.config.RegionConfiguration;

public class RegionTest {

private World world = Mockito.mock(World.class);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The world isn't actually needed, the location computation code does a check that it's not null and a by-reference equals to make sure that the distance is being computed within the same world. Otherwise nothing's needed on it, hence the mockito voodoo.


@Test
public void testHubToHubCost() {
Map<String, Object> cfg = buildBaseConfig();
cfg.put("isHub", true);

Region r1 = new Region("R1", world, new RegionConfiguration(cfg));

cfg.put("x", 1000);
Region r2 = new Region("R2", world, new RegionConfiguration(cfg));

assertEquals("hub to hub travel cost should be zero", 0, r1.getTravelCost(r2));
}

@Test
public void testHubDestinationCost() {
Map<String, Object> cfg = buildBaseConfig();
cfg.put("isHub", true);

Region hub = new Region("hub", world, new RegionConfiguration(cfg));

cfg.put("isHub", false);
cfg.put("x", 1000);
Region region = new Region("region", world, new RegionConfiguration(cfg));

assertEquals("Traveling to a hub should be half as expensive", 1, region.getTravelCost(hub));
}

@Test
public void testHubSourceCost() {
Map<String, Object> cfg = buildBaseConfig();
cfg.put("isHub", true);

Region hub = new Region("hub", world, new RegionConfiguration(cfg));

cfg.put("isHub", false);
cfg.put("x", 1000);
Region region = new Region("region", world, new RegionConfiguration(cfg));

assertEquals("leaving a hub should always cost 1", 1, hub.getTravelCost(region));
}

@Test
public void testRegionCost() {
Map<String, Object> cfg = buildBaseConfig();

Region r1 = new Region("r1", world, new RegionConfiguration(cfg));
cfg.put("x", 1000);
Region r2 = new Region("r2", world, new RegionConfiguration(cfg));

assertEquals("travel cost should be 1xp per 500 blocks", 2, r1.getTravelCost(r2));
}

private static Map<String, Object> buildBaseConfig() {
Map<String, Object> cfg = new HashMap<>();
cfg.put("x", 0);
cfg.put("y", 0);
cfg.put("z", 0);
return cfg;
}
}