forked from Mirrors/openclonk
cable cars: extend order interface and let producer order more components at a time
parent
75a82e172a
commit
a4d20d79d5
|
@ -526,15 +526,14 @@ public func OnEnoughPower(int amount)
|
|||
|
||||
/*-- Delivery --*/
|
||||
|
||||
public func AddRequest(id requested_id, int amount, object target, object source)
|
||||
public func AddRequest(proplist order, object target, object source)
|
||||
{
|
||||
//Log("[%d]AddRequest(car %v at station %v) %v->%v->%v", FrameCounter(), this, lib_ccar_rail, source, [requested_id, amount], target);
|
||||
//Log("[%d]AddRequest(car %v at station %v) %v->%v->%v", FrameCounter(), this, lib_ccar_rail, source, order, target);
|
||||
lib_ccar_delivery =
|
||||
{
|
||||
source = source,
|
||||
target = target,
|
||||
requested_id = requested_id,
|
||||
amount = amount
|
||||
target = target,
|
||||
order = order
|
||||
};
|
||||
// First move to source if not already there.
|
||||
if (lib_ccar_rail != lib_ccar_delivery.source)
|
||||
|
@ -548,7 +547,7 @@ public func ContinueRequest()
|
|||
{
|
||||
if (!lib_ccar_delivery)
|
||||
return;
|
||||
//Log("[%d]ContinueRequest(car %v currently at station %v) %v", FrameCounter(), this, lib_ccar_rail, [lib_ccar_delivery.requested_id, lib_ccar_delivery.amount]);
|
||||
//Log("[%d]ContinueRequest(car %v currently at station %v) %v", FrameCounter(), this, lib_ccar_rail, lib_ccar_delivery.order);
|
||||
// Continue moving to source or target.
|
||||
SetDestination(lib_ccar_delivery.source ?? lib_ccar_delivery.target);
|
||||
}
|
||||
|
@ -557,20 +556,20 @@ public func FinishedRequest(object station)
|
|||
{
|
||||
if (!lib_ccar_delivery)
|
||||
return;
|
||||
//Log("[%d]FinishedRequest(car %v at station %v) %v", FrameCounter(), this, station, [lib_ccar_delivery.requested_id, lib_ccar_delivery.amount]);
|
||||
//Log("[%d]FinishedRequest(car %v at station %v) %v", FrameCounter(), this, station, lib_ccar_delivery.order);
|
||||
// May have first arrived at the source station.
|
||||
if (lib_ccar_delivery.source && station == lib_ccar_delivery.source)
|
||||
{
|
||||
// Load requested objects and move to target.
|
||||
lib_ccar_delivery.source = nil;
|
||||
station->RequestPickUp(this, lib_ccar_delivery.requested_id, lib_ccar_delivery.amount);
|
||||
station->RequestPickUp(this, lib_ccar_delivery.order);
|
||||
SetDestination(lib_ccar_delivery.target);
|
||||
return;
|
||||
}
|
||||
// Arrived at delivery target station.
|
||||
if (station == lib_ccar_delivery.target)
|
||||
{
|
||||
station->RequestArrived(this, lib_ccar_delivery.requested_id, lib_ccar_delivery.amount);
|
||||
station->RequestArrived(this, lib_ccar_delivery.order);
|
||||
lib_ccar_delivery = nil;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -42,14 +42,14 @@ public func OnCableCarDisengaged(object car) { }
|
|||
public func OnCableCarDestruction(object car) { }
|
||||
|
||||
// Called when a cable car wants to pick up resources for a delivery
|
||||
public func OnCableCarPickUp(object car, id requested, int amount) { }
|
||||
public func OnCableCarPickUp(object car, proplist order) { }
|
||||
|
||||
// Called when a cable car with a requested delivery arrives
|
||||
public func OnCableCarDelivery(object car, id requested, int amount) { }
|
||||
public func OnCableCarDelivery(object car, proplist order) { }
|
||||
|
||||
// Called by other stations to check if a certain object and amount are available for delivery at this station.
|
||||
// Return true if there are means to collect the required amount.
|
||||
public func IsAvailable(id requested_id, int amount)
|
||||
public func IsAvailable(proplist order)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -443,35 +443,40 @@ public func GetLengthToTarget(object end)
|
|||
|
||||
local request_queue;
|
||||
|
||||
// Add a new acquiring order
|
||||
public func AddRequest(id requested_id, int amount)
|
||||
// Add a new acquiring order, this order will be delivered to this station and is a proplist with information.
|
||||
// { type = <id of the object>, min_amount = <minimal amount to be delivered>, max_amount = <maximal amount to be delivered>}.
|
||||
public func AddRequest(proplist order)
|
||||
{
|
||||
if (!requested_id) return false;
|
||||
if (!amount) amount = 1;
|
||||
if (!order || !order.type)
|
||||
return false;
|
||||
if (!order.min_amount)
|
||||
order.min_amount = 1;
|
||||
|
||||
// First of all check if a similar request already is on the line
|
||||
// Similar requests will be dismissed, even if they are technically new
|
||||
for (var request in request_queue)
|
||||
if (request[0] == requested_id)
|
||||
if (request[1] == amount)
|
||||
if (request.type == order.type)
|
||||
if (request.min_amount == order.min_amount)
|
||||
return true; // The request is considered handled
|
||||
|
||||
var source = CheckAvailability(requested_id, amount);
|
||||
// Find source station which has the order's items.
|
||||
var source = CheckAvailability(order);
|
||||
if (!source)
|
||||
return false; // Items are not available
|
||||
return false;
|
||||
|
||||
var car = source->GetAvailableCableCar(requested_id, amount, this);
|
||||
// Find cable car that is at source station or closest to source station.
|
||||
var car = source->GetAvailableCableCar(order, this);
|
||||
if (!car)
|
||||
return false; // No cable car is available for delivery
|
||||
return false;
|
||||
|
||||
// Great. Start working immediately
|
||||
PushBack(request_queue, [requested_id, amount]);
|
||||
car->AddRequest(requested_id, amount, this, source);
|
||||
PushBack(request_queue, order);
|
||||
car->AddRequest(order, this, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all connected stations for available objects.
|
||||
public func CheckAvailability(id requested_id, int amount)
|
||||
public func CheckAvailability(proplist order)
|
||||
{
|
||||
var nearest_station;
|
||||
var length_to;
|
||||
|
@ -482,7 +487,7 @@ public func CheckAvailability(id requested_id, int amount)
|
|||
PushBack(network_stations, station[const_finaldestination]);
|
||||
for (var station in network_stations)
|
||||
{
|
||||
if (station->IsAvailable(requested_id, amount))
|
||||
if (station->IsAvailable(order))
|
||||
{
|
||||
if (!nearest_station)
|
||||
{
|
||||
|
@ -513,47 +518,42 @@ public func CheckAvailability(id requested_id, int amount)
|
|||
}
|
||||
|
||||
// Check if there is a cable car ready for delivery
|
||||
public func GetAvailableCableCar(id requested_id, int amount, object requesting_station)
|
||||
public func GetAvailableCableCar(proplist order, object requesting_station)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// A delivery needs to be picked up at this station.
|
||||
public func RequestPickUp(object car, id requested_id, int amount)
|
||||
public func RequestPickUp(object car, proplist order)
|
||||
{
|
||||
OnCableCarPickUp(car, requested_id, amount);
|
||||
OnCableCarPickUp(car, order);
|
||||
}
|
||||
|
||||
// A delivery has arrived, remove it from the queue and handle the request
|
||||
public func RequestArrived(object car, id requested_id, int amount)
|
||||
public func RequestArrived(object car, proplist order)
|
||||
{
|
||||
if (!HasRequest(requested_id, amount))
|
||||
if (!HasRequest(order))
|
||||
return;
|
||||
|
||||
OnCableCarDelivery(car, requested_id, amount);
|
||||
RemoveRequest(requested_id, amount);
|
||||
OnCableCarDelivery(car, order);
|
||||
RemoveRequest(order);
|
||||
}
|
||||
|
||||
public func HasRequest(id requested_id, int amount)
|
||||
public func HasRequest(proplist order)
|
||||
{
|
||||
for (var i = 0; i < GetLength(request_queue); i++)
|
||||
{
|
||||
if (request_queue[i][0] != requested_id)
|
||||
continue;
|
||||
if (request_queue[i][1] != amount)
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
for (var test_order in request_queue)
|
||||
if (test_order.type == order.type && test_order.min_amount == order.min_amount)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public func RemoveRequest(id requested_id, int amount)
|
||||
public func RemoveRequest(proplist order)
|
||||
{
|
||||
for (var i = 0; i < GetLength(request_queue); i++)
|
||||
{
|
||||
if (request_queue[i][0] != requested_id)
|
||||
if (request_queue[i].type != order.type)
|
||||
continue;
|
||||
if (request_queue[i][1] != amount)
|
||||
if (request_queue[i].min_amount != order.min_amount)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -68,17 +68,17 @@ public func DestinationsUpdated()
|
|||
cable->OnRailNetworkUpdate();
|
||||
}
|
||||
|
||||
public func IsAvailable(id requested_id, int amount)
|
||||
public func IsAvailable(proplist order)
|
||||
{
|
||||
// Check resource chute for contents.
|
||||
if (has_resource_chute && ContentsCount(requested_id) >= amount)
|
||||
if (has_resource_chute && ContentsCount(order.type) >= order.min_amount)
|
||||
return true;
|
||||
// Check cable cars idling at this station.
|
||||
if (GetLength(arrived_cars))
|
||||
{
|
||||
for (var car in arrived_cars)
|
||||
{
|
||||
if (car->~IsAvailable(requested_id, amount))
|
||||
if (car->~IsAvailable(order))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -86,44 +86,52 @@ public func IsAvailable(id requested_id, int amount)
|
|||
return false;
|
||||
}
|
||||
|
||||
public func GetAvailableCableCar(id requested_id, int amount, object requesting_station)
|
||||
public func GetAvailableCableCar(proplist order, object requesting_station)
|
||||
{
|
||||
// Check cars that are idling at this station
|
||||
var best;
|
||||
for (var car in arrived_cars)
|
||||
{
|
||||
if (!car->~IsReadyForDelivery(requested_id, amount, requesting_station))
|
||||
if (!car->~IsReadyForDelivery(order, requesting_station))
|
||||
continue;
|
||||
if (!best)
|
||||
best = car;
|
||||
// A car might want to override the search for an available car, mainly because it holds the container
|
||||
// which holds the requested items
|
||||
else if (car->~OverridePriority(requested_id, amount, requesting_station, best))
|
||||
else if (car->~OverridePriority(order, requesting_station, best))
|
||||
best = car;
|
||||
}
|
||||
if (best)
|
||||
return best;
|
||||
|
||||
// Check cars that are idling at the requesting station
|
||||
// Check cars that are idling at other crossings in the network.
|
||||
if (requesting_station != this)
|
||||
{
|
||||
var best = requesting_station->~GetAvailableCableCar(requested_id, amount, requesting_station);
|
||||
if (best)
|
||||
return best;
|
||||
// Find closest cars first.
|
||||
var destinations = GetDestinations();
|
||||
SortArrayByArrayElement(destinations, this.const_distance, false);
|
||||
for (dest in destinations)
|
||||
{
|
||||
var station = dest[this.const_finaldestination];
|
||||
var best = station->~GetAvailableCableCar(order, station);
|
||||
if (best)
|
||||
return best;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
public func OnCableCarPickUp(object car, id requested, int amount)
|
||||
public func OnCableCarPickUp(object car, proplist order)
|
||||
{
|
||||
car = car->~GetAttachedVehicle() ?? car;
|
||||
|
||||
// Take from resource chute if available.
|
||||
if (has_resource_chute)
|
||||
{
|
||||
var amount = Max(order.min_amount, order.max_amount);
|
||||
while (amount > 0)
|
||||
{
|
||||
var item = FindContents(requested);
|
||||
var item = FindContents(order.type);
|
||||
if (!item)
|
||||
break;
|
||||
item->Enter(car);
|
||||
|
@ -135,26 +143,27 @@ public func OnCableCarPickUp(object car, id requested, int amount)
|
|||
if (connected_building)
|
||||
{
|
||||
// TODO: Do we even want this?
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public func OnCableCarDelivery(object car, id requested, int amount)
|
||||
public func OnCableCarDelivery(object car, proplist order)
|
||||
{
|
||||
// Transfer the requested material to the connected producer
|
||||
if (!connected_building)
|
||||
return;
|
||||
|
||||
car = car->~GetAttachedVehicle() ?? car;
|
||||
|
||||
for (var i = 0; i < amount; i++)
|
||||
var amount = Max(order.min_amount, order.max_amount);
|
||||
while (amount > 0)
|
||||
{
|
||||
var item = car->FindContents(requested);
|
||||
var item = car->FindContents(order.type);
|
||||
if (!item)
|
||||
break;
|
||||
item->Enter(connected_building);
|
||||
amount--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -212,17 +212,17 @@ public func DropContents(object station)
|
|||
}
|
||||
|
||||
// Check for available contents
|
||||
public func IsAvailable(id requested_id, int amount)
|
||||
public func IsAvailable(proplist order)
|
||||
{
|
||||
// So far only do something if a lorry is connected, all other vehicles are considered off-limits
|
||||
if (pickup && pickup->~IsLorry())
|
||||
if (pickup->ContentsCount(requested_id) >= amount)
|
||||
if (pickup->ContentsCount(order.type) >= order.min_amount)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called when a station has asked to make a delivery
|
||||
public func IsReadyForDelivery(id requested_id, int amount, object requesting_station)
|
||||
public func IsReadyForDelivery(proplist order, object requesting_station)
|
||||
{
|
||||
// Is already on a delivery.
|
||||
if (lib_ccar_delivery)
|
||||
|
@ -231,20 +231,20 @@ public func IsReadyForDelivery(id requested_id, int amount, object requesting_st
|
|||
if (pickup && pickup->~IsLorry())
|
||||
{
|
||||
// Lorry must have enough space left...
|
||||
if (pickup->ContentsCount() + amount <= pickup.MaxContentsCount)
|
||||
if (pickup->ContentsCount() + order.min_amount <= pickup.MaxContentsCount)
|
||||
return true;
|
||||
// ...or contain the requested objects
|
||||
if (pickup->ContentsCount(requested_id) >= amount)
|
||||
if (pickup->ContentsCount(order.type) >= order.min_amount)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called when searching for a better option to deliver something
|
||||
public func OverridePriority(id requested_id, int amount, object requesting_station, proplist best)
|
||||
public func OverridePriority(proplist order, object requesting_station, object best_car)
|
||||
{
|
||||
// Check if the connected vehicle holds the requested objects and if yes, override the selection
|
||||
if (pickup && pickup->ContentsCount(requested_id) >= amount)
|
||||
if (pickup && pickup->ContentsCount(order.type) >= order.min_amount)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -497,7 +497,7 @@ private func ProcessQueue()
|
|||
if (!Produce(product_id, producing_player))
|
||||
{
|
||||
// No material available? request from cable network.
|
||||
RequestAllMissingComponents(product_id);
|
||||
RequestAllMissingComponents(queue[0]);
|
||||
// In the meanwhile, just cycle the queue and try the next one.
|
||||
CycleQueue();
|
||||
return FX_OK;
|
||||
|
@ -827,34 +827,47 @@ public func ConnectCableStation(object station)
|
|||
/**
|
||||
Requests the necessary material from the cable network if available.
|
||||
*/
|
||||
public func RequestAllMissingComponents(id item_id)
|
||||
public func RequestAllMissingComponents(proplist product)
|
||||
{
|
||||
if (!cable_station)
|
||||
return false;
|
||||
|
||||
|
||||
var item_id = product.Product;
|
||||
var amount = product.Amount;
|
||||
// Take by batches of five for infinite production.
|
||||
// TODO: Can we somehow make this smarter? Take all available from source container?
|
||||
if (product.Infinite)
|
||||
amount = 5;
|
||||
|
||||
// Request all currently unavailable components.
|
||||
for (var item in ProductionCosts(item_id))
|
||||
{
|
||||
var mat_id = item[0];
|
||||
var mat_cost = item[1];
|
||||
// No way to request liquids currently, player must use pumps instead.
|
||||
if (mat_id->~IsLiquid())
|
||||
continue;
|
||||
var available = GetAvailableComponentAmount(mat_id);
|
||||
if (available < mat_cost)
|
||||
RequestObject(mat_id, mat_cost - available);
|
||||
RequestObject(mat_id, mat_cost - available, amount * mat_cost - available);
|
||||
}
|
||||
|
||||
// Also check item fuel need.
|
||||
var fuel_needed = FuelNeed(item_id);
|
||||
if (fuel_needed > 0)
|
||||
{
|
||||
{
|
||||
// For now just use coal as a fuel.
|
||||
RequestObject(Coal, 1 + (fuel_needed - 1) / Coal->GetFuelAmount());
|
||||
var coal_needed = 1 + (fuel_needed - 1) / Coal->GetFuelAmount();
|
||||
RequestObject(Coal, coal_needed, amount * coal_needed);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public func RequestObject(id item_id, int amount)
|
||||
public func RequestObject(id item_id, int min_amount, int max_amount)
|
||||
{
|
||||
if (cable_station)
|
||||
cable_station->AddRequest(item_id, amount);
|
||||
cable_station->AddRequest({type = item_id, min_amount = min_amount, max_amount = max_amount});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -277,7 +277,8 @@ public func RequestFuel()
|
|||
{
|
||||
// For now just request coal as it is the safest type of fuel, that is least needed by other structures.
|
||||
if (cable_station)
|
||||
cable_station->AddRequest(Coal, 1);
|
||||
cable_station->AddRequest({type = Coal, min_amount = 1, max_amount = 5});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue