Skip to content

Commit a7ba069

Browse files
committed
Virtual Machine Support
1 parent 926e1ce commit a7ba069

File tree

6 files changed

+198
-61
lines changed

6 files changed

+198
-61
lines changed

mcav-common/src/main/java/me/brandonli/mcav/media/player/vm/VMConfiguration.java

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
*/
1818
package me.brandonli.mcav.media.player.vm;
1919

20-
import java.util.*;
21-
import org.checkerframework.checker.nullness.qual.KeyFor;
20+
import java.util.ArrayList;
21+
import java.util.Collections;
22+
import java.util.List;
2223

2324
/**
2425
* A builder class for creating QEMU virtual machine configurations.
@@ -27,10 +28,10 @@
2728
*/
2829
public class VMConfiguration {
2930

30-
private final Map<String, String> options;
31+
private final List<String> arguments;
3132

3233
private VMConfiguration() {
33-
this.options = new HashMap<>();
34+
this.arguments = new ArrayList<>();
3435
}
3536

3637
/**
@@ -49,8 +50,7 @@ public static VMConfiguration builder() {
4950
* @return this builder instance
5051
*/
5152
public VMConfiguration memory(final int memoryMB) {
52-
this.options.put("m", memoryMB + "M");
53-
return this;
53+
return this.option("m", memoryMB + "M");
5454
}
5555

5656
/**
@@ -61,8 +61,7 @@ public VMConfiguration memory(final int memoryMB) {
6161
* @return this builder instance
6262
*/
6363
public VMConfiguration memory(final int amount, final String unit) {
64-
this.options.put("m", amount + unit);
65-
return this;
64+
return this.option("m", amount + unit);
6665
}
6766

6867
/**
@@ -72,8 +71,7 @@ public VMConfiguration memory(final int amount, final String unit) {
7271
* @return this builder instance
7372
*/
7473
public VMConfiguration cores(final int cores) {
75-
this.options.put("smp", String.valueOf(cores));
76-
return this;
74+
return this.option("smp", String.valueOf(cores));
7775
}
7876

7977
/**
@@ -83,8 +81,7 @@ public VMConfiguration cores(final int cores) {
8381
* @return this builder instance
8482
*/
8583
public VMConfiguration cdrom(final String isoPath) {
86-
this.options.put("cdrom", isoPath);
87-
return this;
84+
return this.option("cdrom", isoPath);
8885
}
8986

9087
/**
@@ -94,8 +91,7 @@ public VMConfiguration cdrom(final String isoPath) {
9491
* @return this builder instance
9592
*/
9693
public VMConfiguration hda(final String hdaPath) {
97-
this.options.put("hda", hdaPath);
98-
return this;
94+
return this.option("hda", hdaPath);
9995
}
10096

10197
/**
@@ -105,8 +101,7 @@ public VMConfiguration hda(final String hdaPath) {
105101
* @return this builder instance
106102
*/
107103
public VMConfiguration hdb(final String hdbPath) {
108-
this.options.put("hdb", hdbPath);
109-
return this;
104+
return this.option("hdb", hdbPath);
110105
}
111106

112107
/**
@@ -116,8 +111,7 @@ public VMConfiguration hdb(final String hdbPath) {
116111
* @return this builder instance
117112
*/
118113
public VMConfiguration boot(final String bootOrder) {
119-
this.options.put("boot", bootOrder);
120-
return this;
114+
return this.option("boot", bootOrder);
121115
}
122116

123117
/**
@@ -127,8 +121,7 @@ public VMConfiguration boot(final String bootOrder) {
127121
* @return this builder instance
128122
*/
129123
public VMConfiguration network(final String netConfig) {
130-
this.options.put("net", netConfig);
131-
return this;
124+
return this.option("net", netConfig);
132125
}
133126

134127
/**
@@ -138,8 +131,7 @@ public VMConfiguration network(final String netConfig) {
138131
* @return this builder instance
139132
*/
140133
public VMConfiguration cpu(final String model) {
141-
this.options.put("cpu", model);
142-
return this;
134+
return this.option("cpu", model);
143135
}
144136

145137
/**
@@ -149,8 +141,7 @@ public VMConfiguration cpu(final String model) {
149141
* @return this builder instance
150142
*/
151143
public VMConfiguration machine(final String machineType) {
152-
this.options.put("machine", machineType);
153-
return this;
144+
return this.option("machine", machineType);
154145
}
155146

156147
/**
@@ -161,10 +152,10 @@ public VMConfiguration machine(final String machineType) {
161152
*/
162153
public VMConfiguration kvm(final boolean enable) {
163154
if (enable) {
164-
this.options.put("enable-kvm", "");
165-
} else {
166-
this.options.remove("enable-kvm");
155+
return this.flag("enable-kvm");
167156
}
157+
// Remove the flag if it exists
158+
this.arguments.removeIf(arg -> arg.equals("-enable-kvm"));
168159
return this;
169160
}
170161

@@ -175,8 +166,7 @@ public VMConfiguration kvm(final boolean enable) {
175166
* @return this builder instance
176167
*/
177168
public VMConfiguration display(final String displayType) {
178-
this.options.put("display", displayType);
179-
return this;
169+
return this.option("display", displayType);
180170
}
181171

182172
/**
@@ -187,10 +177,10 @@ public VMConfiguration display(final String displayType) {
187177
*/
188178
public VMConfiguration graphics(final boolean enable) {
189179
if (!enable) {
190-
this.options.put("nographic", "");
191-
} else {
192-
this.options.remove("nographic");
180+
return this.flag("nographic");
193181
}
182+
// Remove the flag if it exists
183+
this.arguments.removeIf(arg -> arg.equals("-nographic"));
194184
return this;
195185
}
196186

@@ -201,8 +191,7 @@ public VMConfiguration graphics(final boolean enable) {
201191
* @return this builder instance
202192
*/
203193
public VMConfiguration audio(final String driver) {
204-
this.options.put("audio", driver);
205-
return this;
194+
return this.option("audio", driver);
206195
}
207196

208197
/**
@@ -222,8 +211,7 @@ public VMConfiguration diskSize(final int size) {
222211
* @return this builder instance
223212
*/
224213
public VMConfiguration diskSize(final String size) {
225-
this.options.put("drive", "file=fat:rw:" + size);
226-
return this;
214+
return this.option("drive", "file=fat:rw:" + size);
227215
}
228216

229217
/**
@@ -234,7 +222,13 @@ public VMConfiguration diskSize(final String size) {
234222
* @return this builder instance
235223
*/
236224
public VMConfiguration option(final String key, final String value) {
237-
this.options.put(key, value);
225+
this.arguments.removeIf(arg -> arg.equals("-" + key));
226+
final int valueIndex = this.arguments.indexOf("-" + key) + 1;
227+
if (valueIndex > 0 && valueIndex < this.arguments.size()) {
228+
this.arguments.remove(valueIndex);
229+
}
230+
this.arguments.add("-" + key);
231+
this.arguments.add(value);
238232
return this;
239233
}
240234

@@ -245,17 +239,19 @@ public VMConfiguration option(final String key, final String value) {
245239
* @return this builder instance
246240
*/
247241
public VMConfiguration flag(final String flag) {
248-
this.options.put(flag, "");
242+
if (!this.arguments.contains("-" + flag)) {
243+
this.arguments.add("-" + flag);
244+
}
249245
return this;
250246
}
251247

252248
/**
253-
* Returns an unmodifiable view of the configuration options.
249+
* Returns an unmodifiable view of the configuration arguments.
254250
*
255-
* @return the configured options
251+
* @return the configured arguments list
256252
*/
257-
public Map<String, String> getOptions() {
258-
return Collections.unmodifiableMap(this.options);
253+
public List<String> getArguments() {
254+
return Collections.unmodifiableList(this.arguments);
259255
}
260256

261257
/**
@@ -264,16 +260,6 @@ public Map<String, String> getOptions() {
264260
* @return a string array of QEMU arguments
265261
*/
266262
public String[] buildArgs() {
267-
final List<String> args = new ArrayList<>();
268-
final Set<Map.Entry<@KeyFor("this.options") String, String>> entries = this.options.entrySet();
269-
for (final Map.Entry<String, String> entry : entries) {
270-
final String key = entry.getKey();
271-
final String value = entry.getValue();
272-
args.add("-" + key);
273-
if (!value.isEmpty()) {
274-
args.add(value);
275-
}
276-
}
277-
return args.toArray(new String[0]);
263+
return this.arguments.toArray(new String[0]);
278264
}
279265
}

sandbox/src/main/java/me/brandonli/mcav/sandbox/command/AnnotationParserHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public final class AnnotationParserHandler {
4141
new VideoControlCommand(),
4242
new VideoEntityCommand(),
4343
new VideoChatCommand(),
44-
new VideoScoreboardCommand()
44+
new VideoScoreboardCommand(),
45+
new VirtualizeCommand()
4546
);
4647

4748
private final CommandManager<CommandSender> manager;

sandbox/src/main/java/me/brandonli/mcav/sandbox/command/BrowserCommand.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@
3737
import me.brandonli.mcav.sandbox.utils.ArgumentUtils;
3838
import me.brandonli.mcav.sandbox.utils.DitheringArgument;
3939
import me.brandonli.mcav.utils.immutable.Pair;
40-
import org.bukkit.Bukkit;
4140
import org.bukkit.command.CommandSender;
42-
import org.bukkit.entity.Player;
4341
import org.checkerframework.checker.nullness.qual.Nullable;
42+
import org.incendo.cloud.annotation.specifier.Greedy;
4443
import org.incendo.cloud.annotation.specifier.Quoted;
4544
import org.incendo.cloud.annotation.specifier.Range;
4645
import org.incendo.cloud.annotations.*;
46+
import org.incendo.cloud.bukkit.data.MultiplePlayerSelector;
4747

4848
public final class BrowserCommand implements AnnotationCommandFeature {
4949

@@ -55,7 +55,7 @@ public void registerFeature(final MCAVSandbox plugin, final AnnotationParser<Com
5555
@Command("mcav browser release")
5656
@Permission("mcav.browser.release")
5757
@CommandDescription("mcav.command.browser.release.info")
58-
public void playBrowser(final CommandSender player) {
58+
public void releaseBrowser(final CommandSender player) {
5959
if (this.browser != null) {
6060
try {
6161
this.browser.release();
@@ -67,16 +67,17 @@ public void playBrowser(final CommandSender player) {
6767
player.sendMessage(Message.RELEASE_BROWSER.build());
6868
}
6969

70-
@Command("mcav browser create <browserResolution> <blockDimensions> <mapId> <ditheringAlgorithm> <url>")
70+
@Command("mcav browser create <playerSelector> <browserResolution> <blockDimensions> <mapId> <ditheringAlgorithm> <url>")
7171
@Permission("mcav.command.browser.create")
7272
@CommandDescription("mcav.command.browser.create.info")
7373
public void playBrowser(
7474
final CommandSender player,
75+
final MultiplePlayerSelector playerSelector,
7576
@Argument(suggestions = "resolutions") @Quoted final String browserResolution,
7677
@Argument(suggestions = "dimensions") @Quoted final String blockDimensions,
7778
@Argument(suggestions = "ids") @Range(min = "0") final int mapId,
7879
final DitheringArgument ditheringAlgorithm,
79-
@Quoted final String url
80+
@Greedy final String url
8081
) {
8182
final Pair<Integer, Integer> resolution;
8283
final Pair<Integer, Integer> dimensions;
@@ -115,7 +116,7 @@ public void playBrowser(
115116
final int blockWidth = dimensions.getFirst();
116117
final int blockHeight = dimensions.getSecond();
117118

118-
final Collection<UUID> players = Bukkit.getOnlinePlayers().stream().map(Player::getUniqueId).toList();
119+
final Collection<UUID> players = ArgumentUtils.parsePlayerSelectors(playerSelector);
119120
final MapConfiguration configuration = MapConfiguration.builder()
120121
.map(mapId)
121122
.mapBlockHeight(blockHeight)

0 commit comments

Comments
 (0)