This problem doesn't have a solution to me but I hope you will. I have only experienced forge modding in 1.16.5 and in 1.18.1, there is so much Confusion, My Brain is Literally Broken and I have Dizziness just looking at it. I followed a code from 1.17 from TurtyWurty and this is it:
public static final List<ConfiguredFeature<?, ?>> OVERWORLD_ORES = new ArrayList<>();
public static final List<ConfiguredFeature<?, ?>> END_ORES = new ArrayList<>();
public static final List<ConfiguredFeature<?, ?>> NETHER_ORES = new ArrayList<>();
public static final RuleTest END_TEST = new BlockMatchTest(Blocks.END_STONE);
public static void registerOres() {
ConfiguredFeature<?, ?> bronzeOre = Feature.ORE
.configured(new OreConfiguration(List.of(
OreConfiguration.target(OreFeatures.STONE_ORE_REPLACEABLES,
Blocks.GLOWSTONE.defaultBlockState())),
11));
bronzeOre.placed(commonOrePlacement(8, HeightRangePlacement.triangle(VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(20))));
OVERWORLD_ORES.add(register("bronze_ore", bronzeOre));
}
private static <Config extends FeatureConfiguration> ConfiguredFeature<Config, ?> register(String name,
ConfiguredFeature<Config, ?> configuredFeature) {
return Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(FendersMetalMod.MOD_ID, name),
configuredFeature);
}
#Mod.EventBusSubscriber(modid = FendersMetalMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public static class ForgeBusSubscriber {
#SubscribeEvent
public static void biomeLoading(BiomeLoadingEvent event) {
List<Supplier<ConfiguredFeature<?, ?>>> features = event.getGeneration()
.getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);
switch(event.getCategory()) {
default -> MetalOreGen.OVERWORLD_ORES.forEach(ore -> features.add(() -> ore));
}
}
}
private static List<PlacementModifier> orePlacement(PlacementModifier p_195347_, PlacementModifier p_195348_) {
return List.of(p_195347_, InSquarePlacement.spread(), p_195348_, BiomeFilter.biome());
}
private static List<PlacementModifier> commonOrePlacement(int p_195344_, PlacementModifier p_195345_) {
return orePlacement(CountPlacement.of(p_195344_), p_195345_);
}
But the code has a problem, see in this part of the code:
List<Supplier<ConfiguredFeature<?, ?>>> features = event.getGeneration()
.getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);
It has an error in which I don't know but I think that:
"event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);"
is not correct and should provide a "List<Supplier<ConfiguredFeature<?, ?>>>"
because "event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES);"
is a "List<Supplier<PlacedFeature>>", not a "List<Supplier<ConfiguredFeature<?, ?>>>".
I tried to change it but there are more errors that would appear if I would Change it.
Related
I would like to use the MMDevice API from my Java app. What are my options?
I tried to use JNA. Looks like I can't use JNA Typelib parsing because there no types for this API (Is there a COM type library for Windows Core Audio). As suggested, I need to provide my own declarations of the API.
So I also tried both JNA examples with manual declarations but they give "Interface not supported HRESULT=80004002" error:
public class MMDeviceAPITest {
public static void test1() {
try {
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
var obj = new Test1.MMDeviceEnumerator(); // exception E_NOINTERFACE (HRESULT: 80004002)
// ...
} finally {
Ole32.INSTANCE.CoUninitialize();
}
}
public static void test2() {
try {
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
var factory = new Factory();
var obj = factory.createObject(Test2.MMDeviceEnumerator.class); // exception E_NOINTERFACE (HRESULT: 80004002)
var in = obj.queryInterface(Test2.IMMDeviceEnumerator.class);
// ...
} finally {
Ole32.INSTANCE.CoUninitialize();
}
}
}
interface Test1 {
class MMDeviceEnumerator extends COMLateBindingObject {
public MMDeviceEnumerator() {
super(new Guid.CLSID("bcde0395-e52f-467c-8e3d-c4579291692e"), true);
}
}
}
interface Test2 {
#ComObject(clsId = "bcde0395-e52f-467c-8e3d-c4579291692e")
interface MMDeviceEnumerator extends IUnknown {} // doesn't extend IUnknown in C sources, probably it's the problem...
#ComInterface(iid = "a95664d2-9614-4f35-a746-de8db63617e6")
interface IMMDeviceEnumerator extends IUnknown {}
}
Any ideas how I could access this API from Java? Can I somehow create working declarations for JNA? Or use another framework maybe?
My last idea is to create/find a micro native app/library that wraps the needed COM calls, so I could call this app/library easily (via subprocesses or simple JNA declarations). I'm new to COM world, but it sounds working for me...
The docs you linked show how to create using CoCreateInstance:
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
hr = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);
This should get you somewhere close with JNA.
class MMDeviceEnumerator extends Unknown {
public static final CLSID CLSID_MMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e");
public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6");
public MMDeviceEnumerator(Pointer p) {
super(p);
}
public static MMDeviceEnumerator create() {
PointerByReference pEnumerator = new PointerByReference();
HRESULT hres = Ole32.INSTANCE.CoCreateInstance(
CLSID_MMDeviceEnumerator, null,
WTypes.CLSCTX_ALL, IID_IMMDeviceEnumerator,
pEnumerator);
if (COMUtils.FAILED(hres)) {
return null;
}
return new MMDeviceEnumerator(pEnumerator.getValue());
}
// map functions as needed
}
I used the implementation of IWbemContext in JNA as a template above. You can consult that class for example COM function mappings.
For some reason I can't suggest edits to the answer of Daniel Widdis. The answer worked for me, many thanks! Just wanted to show how to map one method as an example:
class MMDeviceEnumerator extends Unknown {
public static final CLSID CLSID_MMDeviceEnumerator = new CLSID("bcde0395-e52f-467c-8e3d-c4579291692e");
public static final GUID IID_IMMDeviceEnumerator = new GUID("a95664d2-9614-4f35-a746-de8db63617e6");
public MMDeviceEnumerator(Pointer p) {
super(p);
}
public static MMDeviceEnumerator create() {
PointerByReference pEnumerator = new PointerByReference();
HRESULT hres = Ole32.INSTANCE.CoCreateInstance(
CLSID_MMDeviceEnumerator, null,
WTypes.CLSCTX_ALL, IID_IMMDeviceEnumerator, pEnumerator);
if (COMUtils.FAILED(hres)) {
return null;
}
return new MMDeviceEnumerator(pEnumerator.getValue());
}
public static final int EDataFlow_eRender = 0;
public static final int EDataFlow_eCapture = 1;
public static final int EDataFlow_eAll = 2;
public static final int EDataFlow_enum_count = 3;
public static final int DEVICE_STATE_ACTIVE = 0x1;
public static final int DEVICE_STATE_DISABLED = 0x2;
public static final int DEVICE_STATE_NOTPRESENT = 0x4;
public static final int DEVICE_STATE_UNPLUGGED = 0x8;
public static final int DEVICE_STATEMASK_ALL = 0xF;
public void EnumAudioEndpoints(int dataFlow, int dwStateMask, PointerByReference ppDevices) {
WinNT.HRESULT res = (WinNT.HRESULT) _invokeNativeObject(
3, // `EnumAudioEndpoints` is the 3rd method of `IMMDeviceEnumeratorVtbl` in `mmdeviceapi.h`
new Object[] { getPointer(), dataFlow, new WinDef.DWORD(dwStateMask), ppDevices},
WinNT.HRESULT.class
);
COMUtils.checkRC(res);
}
// map other functions as needed
}
I have this code where I have defined two classes using generics.
1. Section which can have a generic type of data.
2. Config which uses kind of builder patterns and stores list of such sections.
On running this code it gives compilation error and I am no where to understand why. I have mentioned the type.
Error : incompatible types: java.util.List> cannot be converted to java.util.List>
public class Main {
public static void main(String[] args) {
Section<String> section = new Section<>("wow");
List<Section<String>> sections = new ArrayList<>();
sections.add(section);
Config<String> config = new Config<>().setSections(sections);
}
public static class Section<T> {
private T data;
public Section(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
public static class Config<T> {
private List<Section<T>> sections;
public Config() {
}
public Config<T> setSections(List<Section<T>> sections) {
this.sections = sections;
return this;
}
}
}
The problem is at line 7, you are creating new Config and call setSections on the same line.
So the solutions are two:
Explicit type:
Config<String> config = new Config<String>().setSections(sections);
Split operations:
Config<String> config = new Config<>();
conf.setSections(sections);
It's a compiler peculiarity, you'll have to write
Config<String> config = new Config<String>().setSections(sections);
I have a question on the use of IO operations within java.util.function.Predicate. Please consider the following example:
public class ClientGroupFilter implements Predicate<Client> {
private GroupMapper mapper;
private List<String> validGroupNames = new ArrayList<>();
public ClientGroupFilter(GroupMapper mapper) {
this.mapper = mapper;
}
#Override
public boolean test(Client client) {
// this is a database call
Set<Integer> validsIds = mapper.getValidIdsForGroupNames(validGroupNames);
return client.getGroupIds().stream().anyMatch(validIds::contains);
}
public void permit(String name) {
validGroupNames.add(name);
}
}
As you can see this filter accepts any number of server group names, which are resolved by the mapper when a specific client is tested. If the client owns one of the valid server groups, true is returned.
Now, of course it is obivous that this is totally iniffecient if the filter is applied to multiple clients. So, refactoring lead me to this:
public class ClientGroupFilter implements Predicate<Client> {
private GroupMapper mapper;
private List<String> validGroupNames = new ArrayList<>();
private boolean updateRequired = true;
private Set<Integer> validIds = new HashSet<>();
public ClientGroupFilter(GroupMapper mapper) {
this.mapper = mapper;
}
#Override
public boolean test(Client client) {
if(updateRequired) {
// this is a database call
validIds = mapper.getValidIdsForGroupNames(validGroupNames);
updateRequired = false;
}
return client.getGroupIds().stream().anyMatch(validIds::contains);
}
public void permit(String name) {
validGroupNames.add(name);
updateRequired = true;
}
}
The performance is a lot better, of course, but im still not happy with the solution, since i feel like java.util.function.Predicate should not be used like this. However, i still want to be able to provide a fast solution to filter a list of clients, without the need to require the consumer to map the server group name to its ids.
Does anyone have a better idea to refactor this?
If your usage pattern is such that you call permit several times, and then use Predicate<Client> without calling permit again, you can separate the code that collects validGroupNames from the code of your predicate by using a builder:
class ClientGroupFilterBuilder {
private final GroupMapper mapper;
private List<String> validGroupNames = new ArrayList<>();
public ClientGroupFilter(GroupMapper mapper) {
this.mapper = mapper;
}
public void permit(String name) {
validGroupNames.add(name);
}
public Predicate<Client> build() {
final Set<Integer> validIds = mapper.getValidIdsForGroupNames(validGroupNames);
return new Predicate<Client>() {
#Override
public boolean test(Client client) {
return client.getGroupIds().stream().anyMatch(validIds::contains);
}
}
}
}
This restricts building of validIds to the point where we construct the Predicate<Client>. Once the predicate is constructed, no further input is necessary.
I've searched the internet for something to similar to what I'm doing, but haven't found anything. I'm using interfaces in Java 8 to create a Builder pattern, like so:
public class UrlImmutable {
public final String parentUrl;
public final Double parentUrlSentiment;
public final Set<String> childUrls;
public final boolean isParentVendorUrl;
public final Map<TagClassification, Set<String>> parentUrlArticleTags;
private UrlImmutable(String parentUrl, Double parentUrlSentiment, Set<String> childUrls, boolean isParentVendorUrl,
Map<TagClassification, Set<String>> parentUrlArticleTags ) {
super();
this.parentUrl = parentUrl;
this.parentUrlSentiment = parentUrlSentiment;
this.childUrls = childUrls;
this.isParentVendorUrl = isParentVendorUrl;
this.parentUrlArticleTags = parentUrlArticleTags;
}
/** Our Interfaces for the Builder **/
public interface ParentUrlBuilder {
ParentUrlSentimentBuilder parentUrl(String parentUrl);
}
public interface ParentUrlSentimentBuilder {
ChildUrlBuilder parentUrlSentiment(Double parentUrlSentiment);
}
public interface ChildUrlBuilder {
IsVendorUrlBuilder childUrls(Set<String> childUrls);
}
public interface IsVendorUrlBuilder {
ParentUrlArticleTagsBuilder isParentVendorUrl(boolean isParentVendorUrl);
}
public interface ParentUrlArticleTagsBuilder {
UrlImmutable parentUrlArticleTags(Map<TagClassification,Set<String>> parentUrlArticleTags);
}
public static ParentUrlBuilder discoveredUrl() {
return parentUrl -> parentUrlSentiment -> childUrls -> isParentVendorUrl -> parentUrlArticleTags ->
new UrlImmutable(parentUrl, parentUrlSentiment, childUrls, isParentVendorUrl, parentUrlArticleTags);
}
}
And to construct this object, we do this:
UrlImmutable url =
UrlImmutable()
.parentUrl("http://www.google.com")
.parentUrlSentiment(10.5)
.childUrls(childUrls)
.isParentVendorUrl(true)
.parentUrlArticleTags(parentUrlArticleTags);
I can't seem to find the right combination of annotations for this. Any help much appreciated!
I am very new to Akka and using Java to program my system.
Problem definition
- I have a TenantMonitor which when receives TenantMonitorMessage(), starts a new actor DiskMonitorActor.
- The DiskMonitorActor may fail for various reasons and may throw DiskException. The DiskMonitorActor has been Unit Tested.
What I need?
- I want to test behavior TenantMonitorActor, so that when DiskException happens, it takes correct action like stop(), resume() or any (depending upon what my application may need)
What I tried?
Based on the documentation, the closest I could perform is the section called Expecting Log Messages.
Where I need help?
- While I understand the expecting the correct error log is important, it just asserts first part, that exception is thrown and is logged correctly, but does not help in asserting that right strategy is called
Code?
TenantMonitorActor
public class TenantMonitorActor extends UntypedActor {
public static final String DISK_MONITOR = "diskMonitor";
private static final String assetsLocationKey = "tenant.assetsLocation";
private static final String schedulerKey = "monitoring.tenant.disk.schedule.seconds";
private static final String thresholdPercentKey = "monitoring.tenant.disk.threshold.percent";
private final LoggingAdapter logging = Logging.getLogger(getContext().system(), this);
private final Config config;
private TenantMonitorActor(final Config config) {
this.config = config;
}
private static final SupervisorStrategy strategy =
new OneForOneStrategy(1, Duration.create(1, TimeUnit.SECONDS),
new Function<Throwable, Directive>() {
public Directive apply(final Throwable param) throws Exception {
if (param instanceof DiskException) {
return stop();
}
return restart();
}
});
public static Props props(final Config config) {
return Props.create(new Creator<TenantMonitorActor>(){
public TenantMonitorActor create() throws Exception {
return new TenantMonitorActor(config);
}
});
}
#Override
public void onReceive(final Object message) throws Exception {
if (message instanceof TenantMonitorMessage) {
logging.info("Tenant Monitor Setup");
setupDiskMonitoring();
}
}
#Override
public SupervisorStrategy supervisorStrategy() {
return strategy;
}
private void setupDiskMonitoring() {
final ActorRef diskMonitorActorRef = getDiskMonitorActorRef(config);
final FiniteDuration start = Duration.create(0, TimeUnit.SECONDS);
final FiniteDuration recurring = Duration.create(config.getInt(schedulerKey),
TimeUnit.SECONDS);
final ActorSystem system = getContext().system();
system.scheduler()
.schedule(start, recurring, diskMonitorActorRef,
new DiskMonitorMessage(), system.dispatcher(), null);
}
private ActorRef getDiskMonitorActorRef(final Config monitoringConf) {
final Props diskMonitorProps =
DiskMonitorActor.props(new File(monitoringConf.getString(assetsLocationKey)),
monitoringConf.getLong(thresholdPercentKey));
return getContext().actorOf(diskMonitorProps, DISK_MONITOR);
}
}
Test
#Test
public void testActorForNonExistentLocation() throws Exception {
final Map<String, String> configValues =
Collections.singletonMap("tenant.assetsLocation", "/non/existentLocation");
final Config config = mergeConfig(configValues);
new JavaTestKit(system) {{
assertEquals("system", system.name());
final Props props = TenantMonitorActor.props(config);
final ActorRef supervisor = system.actorOf(props, "supervisor");
new EventFilter<Void>(DiskException.class) {
#Override
protected Void run() {
supervisor.tell(new TenantMonitorMessage(), ActorRef.noSender());
return null;
}
}.from("akka://system/user/supervisor/diskMonitor").occurrences(1).exec();
}};
}
UPDATE
The best I could write is to make sure that the DiskMonitor is stopped once the exception occurs
#Test
public void testSupervisorForFailure() {
new JavaTestKit(system) {{
final Map<String, String> configValues =
Collections.singletonMap("tenant.assetsLocation", "/non/existentLocation");
final Config config = mergeConfig(configValues);
final TestActorRef<TenantMonitorActor> tenantTestActorRef = getTenantMonitorActor(config);
final ActorRef diskMonitorRef = tenantTestActorRef.underlyingActor().getContext()
.getChild(TenantMonitorActor.DISK_MONITOR);
final TestProbe testProbeDiskMonitor = new TestProbe(system);
testProbeDiskMonitor.watch(diskMonitorRef);
tenantTestActorRef.tell(new TenantMonitorMessage(), getRef());
testProbeDiskMonitor.expectMsgClass(Terminated.class);
}};
}
Are there better ways?
I have the feeling that testing supervisor strategy is some sort of grey area -- it is up to personal opinion where we start testing Akka itself, instead of one's understanding of how the framework works. Testing validation of entities in ORM frameworks strikes me as a similar problem. We don't want to test whether email validation logic is correct (e.g. in Hibernate), but rather if our rule is correctly declared.
Following this logic, I would write the test as follows:
final TestActorRef<TenantMonitorActor> tenantTestActorRef =
getTenantMonitorActor(config);
SupervisorStrategy.Directive directive = tenantTestActorRef.underlyingActor()
.supervisorStrategy().decider().apply(new DiskException());
assertEquals(SupervisorStrategy.stop(), directive);