85 lines
4.0 KiB
Java
85 lines
4.0 KiB
Java
package uulm.teamname.marvelous.server.game.pipelining;
|
|
|
|
import org.tinylog.Logger;
|
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
|
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
|
import uulm.teamname.marvelous.server.net.Client;
|
|
|
|
import java.util.*;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
/**
|
|
* The {@link Pipeline} class pipelines {@link Request Requests} through {@link Segment Segments} to create {@link Event
|
|
* Events}. To add functionality without dabbling in the game library, create a new {@link Segment}.
|
|
*/
|
|
public class Pipeline {
|
|
|
|
/** The segments of the pipeline, which will be executed from left to right (index 0 to segments.size()) */
|
|
private final ArrayList<Segment> segments;
|
|
|
|
/**
|
|
* Creates a new empty {@link Pipeline} object
|
|
*/
|
|
public Pipeline() {
|
|
this.segments = new ArrayList<>();
|
|
}
|
|
|
|
/**
|
|
* Pipeline the {@link Request Requests} through all {@link Segment Segments} that are in the pipeline. The {@link
|
|
* Request Requests} are declared as the <b>Packet</b>. The {@link Request Requests} are filtered by each {@link
|
|
* Segment segment}, whereby each {@link Segment segment} takes (and thereby removes) all {@link Event events}
|
|
* relevant to the {@link Segment segment}. The {@link Event Events} are returned at the end of the pipeline.
|
|
*
|
|
* @param requests are the requests that are being pipelined through the pipeline
|
|
* @return a {@link Optional}<{@link Event}[]>, whereby the state of the {@link Optional} declares whether the
|
|
* execution of the {@link Pipeline} was successful. <b>If the optional is empty, the input requests were invalid,
|
|
* and an error message can be sent to the client</b>. To get the {@link Event Events} out of the {@link Optional},
|
|
* first check whether the {@link Optional} is empty by doing {@link Optional#isEmpty()} or {@link
|
|
* Optional#isPresent()}, and act accordingly.
|
|
*/
|
|
public Optional<List<Event>> processRequests(Client origin, Request[] requests) {
|
|
Logger.trace("Pipeline started RequestProcessing");
|
|
// The packet carries the requests, and gets smaller per segment
|
|
Packet packet = new Packet(requests, origin);
|
|
// The packet is filled by the requests resulting from events per segment
|
|
List<Event> carrier = new ArrayList<>();
|
|
// The abort boolean describes whether an abort happened in a segment
|
|
AtomicBoolean abort = new AtomicBoolean(false);
|
|
|
|
Logger.trace("Iterating through segments");
|
|
// Loop through all segments
|
|
for (Segment segment : segments) {
|
|
// Give the segment the packet, carrier and abort, and let it process requests
|
|
segment.processRequests(packet, carrier, abort);
|
|
if (packet.isEmpty() || abort.get()) { // if packet is empty (all requests processed) or abort initiated
|
|
break; // (abort boolean true), break out of the loop
|
|
}
|
|
}
|
|
if (abort.get()) { // if abort is true, return empty optional
|
|
Logger.debug("Abort triggered in Pipeline");
|
|
return Optional.empty();
|
|
} else { // else return an optional of the array
|
|
Logger.trace("Pipeline executed normally. Returning {} events.", carrier.size());
|
|
return Optional.of(carrier);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a segment to the pipeline. Note that <b>ORDER MATTERS!</b> The first segment added will be the first segment
|
|
* to process events. Also note that segments <b>cannot be removed once added</b>. This is by design, as removing
|
|
* segments would give the pipeline runtime customizability, which it is not supposed to possess in the first
|
|
* place.
|
|
*
|
|
* @param toAdd is the segment that will be added to the pipeline
|
|
* @return the pipeline itself for chaining
|
|
*/
|
|
public Pipeline addSegment(Segment toAdd) {
|
|
this.segments.add(toAdd);
|
|
return this;
|
|
}
|
|
|
|
public boolean contains(Segment segment) {
|
|
return segments.contains(segment);
|
|
}
|
|
}
|