Far Cry 5 Coop Review

The Far Cry series has been going on for several years now without changing too much of the core game mechanics since the first Far Cry I have played – which was Far Cry 3. What’s new in FC5 is a coop mode that lets you play the main campaign with a buddy. Far Cry 3 had some form of coop as well, but it worked differently by presenting a story unrelated to the game’s single player campaign. I’m not sure how version 4 handled multiplayer, but to my knowledge Far Cry 5 is the first Far Cry to support coop gameplay. It has a few quirks though, which unfortunately still doesn’t make it a 100% coop enabled game. We nevertheless decided to give it a spin and here are my thoughts about the game, its story and gameplay and how the coop experience was.

Read More »

Spring @ConfigurationProperty a Bean or not?

Semi-recently (“semi” because procrastination kept me from writing, so it’s more like two months ago, but blog posts have to start with “recently” when you try to explain yourself why you are writing what you are writing – but I’m getting sidetracked here, so let’s move on) I was wondering whether Java classes annotated with Spring’s @ConfigurationProperty should be declared as a bean, e.g. with @Component. I didn’t find a definitive answer, but I found three ways on how to do it – typical Spring, I guess.

Here’s a quick setup:

My configuration class.

package com.thecodeslinger.configpropsdemo;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; 

@Data 
@ConfigurationProperties(prefix = "demo")
public class Configuration {

    private String elegy;
}

My main application:

package com.thecodeslinger.configpropsdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.PostConstruct;

@SpringBootApplication
public class ConfigPropsDemoApplication {

   @Autowired
   private Configuration configuration;

   @PostConstruct
   public void postConstruct() {
      System.out.println(configuration.getElegy());
   }

   public static void main(String[] args) {
      SpringApplication.run(ConfigPropsDemoApplication.class, args);
   }
}

And finally, my properties file:

demo.elegy=R.I.P. Kobe

It’s not an elegant setup, but that’s not the point. It does the job for now.

If you run the application in this state, Spring will greet you with an error message.

APPLICATION FAILED TO START

Description:
Field configuration in com.thecodeslinger.configpropsdemo.ConfigPropsDemoApplication required a bean of type 'com.thecodeslinger.configpropsdemo.Configuration' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.thecodeslinger.configpropsdemo.Configuration' in your configuration.

It obviously cannot find the configuration bean.

Option #1: Slap @Component to it.

package com.thecodeslinger.configpropsdemo;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "demo")
public class Configuration {

    private String elegy;
}

Option #2: Use the @EnableConfigurationProperties annotation.

import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(Configuration.class)
public class ConfigPropsDemoApplication {

Option #3: Use @ConfigurationPropertiesScan to explicitly name the packages to scan for.

import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

@SpringBootApplication
@ConfigurationPropertiesScan({"com.thecodeslinger.configpropsdemo"})
public class ConfigPropsDemoApplication {

All three options achieve what you’re aiming for, a running application.

:: Spring Boot :: (v2.2.4.RELEASE)
2020-02-03 19:57:43.562 INFO 4612 --- [ main] c.t.c.ConfigPropsDemoApplication : Starting ConfigPropsDemoApplication on DESKTOP-C0O3OKC with PID 4612 (D:\OneDrive\Code\Java\config-props-demo\target\classes started by lober in D:\OneDrive\Code\Java\config-props-demo)
2020-02-03 19:57:43.562 INFO 4612 --- [ main] c.t.c.ConfigPropsDemoApplication : No active profile set, falling back to default profiles: default
R.I.P. Kobe
2020-02-03 19:57:43.921 INFO 4612 --- [ main] c.t.c.ConfigPropsDemoApplication : Started ConfigPropsDemoApplication in 0.573 seconds (JVM running for 1.083)

So, is there any benefit of one over the other? The Spring documentation has the following to say:

Sometimes, classes annotated with @ConfigurationProperties might not be suitable for scanning, for example, if you’re developing your own auto-configuration or you want to enable them conditionally. In these cases, specify the list of types to process using the @EnableConfigurationProperties annotation. This can be done on any @Configuration class, as shown in the following example:

I’m not using a @Configuration class in my example, but if you were, you could leverage that to load your configuration classes based on @Profile annotations. Although @Component works too, it’s not mentioned in that part of the Spring documentation (“Type-safe Configuration Properties”).

For myself, I might go with @EnableConfigurationProperties and if it makes sense, even have dedicated @Configuration classes linked to @Profile. For little samples like this one it’s obviously overkill. In a remotely useful application, the additional overhead may be worth it for structural and documentational reasons.

Ghost Recon: Wildlands – Coop Review

It was a dark night. Rain was pouring relentlessly from the heavens as a helicopter made its way across the border to Bolivia, going unnoticed against the black clouds. Any of the chopper’s noises were suppressed by the droning rain and constant thunder in the sky. Its destination was a remote location, a secret safe house where an equally secret meeting will be held. The helicopter’s passengers were a group of well-trained covert operatives and their handler. These were the kind of people you only call upon in dire need, when circumstances don’t allow anything other than an elite group of soldiers that can get any job done regardless of difficulty or danger. And all that without ever being noticed. They are effectively ghosts and haunt whomever they have been unleashed on. This time around their target is El Sueño, the biggest and most ruthless drug lord in Bolivia.

And this is where you as the player come in. The story is nothing particularly spectacular, but it provides a good enough canvas for an entertaining open world action game that justifies why you do what you do. I’ve played this game all the way to end in coop mode and this my review of the roughly 75 hours it took.

Read More »

AMD Radeon RX 5700 XT Stuttering at 1080p

Quick note before I go into any details: I did not find a solution for this problem, unfortunately. I’ll be explaining what happened and show frame time graphs as proof.

So, with that out of the way, let’s get into it. I’m certainly not the only one with this issue. If you employ the search engine of your liking you will find many threads covering that topic (like here and here and here and here and so on). Some managed to get it working, some did not. I’m obviously in the latter category.

What happens? From what I found in my research it seems like the RX 5700 XT GPU aggressively tries to save energy if it is not fully utilized. If you run MSI’s Afterburner or any other monitoring software, then you’ll see the GPU load and frequency being all over the place. In general, this is a good thing – if it does not affect perceived performance. And this is where it fell apart for me.

Read More »

Wolfenstein: Youngblood – Coop Review

Wolfenstein Youngblood follows in the same footsteps as its three predecessors that sucessfully revived the series in 2009. Having liked Wolfenstein, The New Order and The New Colossus I thought that sharing that kind of game with a friend in Coop would be even better. This is the first installement in this series that allows you to do that and I’m a big fan of Coop gameplay. And by Coop I mean playing the regular campaign with a fellow gamer, not some unrelated multiplayer map or basic PvP action. I want to experience the story with somebody, have a ton of fun and discuss the game while playing it.

Read More »

Ryzen Master not Resetting to “Auto” Control Mode

Recently I set out to figure out how much clock speed I can squeeze out of my Zen+ based Ryzen 5 2600. To make life easier I figured I use Ryzen Master so I can change the settings while I’m in Windows so I don’t have to reboot every time I increase the clock speed. This has worked nicely until the point where I figured the viable maximum was. The next step was to dial those numbers "into hardware", meaning setting the options in the BIOS so that Ryzen Master is not required any more. And this is where my issues started to appear.

The Error

First, here’s a screenshot of the message Ryzen Master was giving me. After that I’ll explain what had happened.

In order to set the CPU multiplier you have to change from automatic to manual mode in Ryzen Master. I wanted to reset all options to their defaults after setting the overclock in the BIOS, but I always kept getting the message that Ryzen Master wants to restart Windows because the setting was changed to "Manual" – which it wasn’t, but more on that later. So I did as it asked multiple times with the same outcome every time. Effectively, I was doing a boot loop manually.

So, how did I get there?

The Journey

In brief:

  • Find a stable overclock in Windows using Ryzen Master.
  • Reboot to BIOS and set the overclock closer to the hardware.
  • Reboot to Windows and reset everything in Ryzen Master.
  • Manual "Boot Loop" a few times.
  • Notice CPU always at 4GHz, no more Cool’n’Quiet operation mode.
  • Undo overclock in BIOS.
  • Still see overclock in Windows.
  • Uninstalling Ryzen Master.
  • Still see overclock in Windows.
  • Ryzen Master still not resetting.
  • Manual "Boot Loop" a few more times.
  • Getting pissed and searching the Internet – apparantly I was not alone.
  • More reboots and tests with BIOS settings.

The Fix

It was the frickin’ BIOS! Ryzen Master was not to blame.

I have an ASRock B450 Gaming mITX mainboard with the latest non-Matisse (Ryzen 3000) BIOS. It is not recommended to upgrade unless a Ryzen 3000 is installed. There’s a weird bug in the BIOS that still applies the overclock even if the setting is set to "Auto by AMD CBS" (or something like that). There were two things that helped:

  1. Load BIOS defaults.
  2. Enable manual control and set the correct CPU base frequency at 3400MHz.

When applying the overclock with 4000MHz it effectly ran at 4GHz every time, even in idle. When setting 3400MHz it properly clocked down and also boosted as a R5 2600 should. The same setting only with a different clock value produced a different behavior. And unless the BIOS defaults are loaded the "Auto" mode doesn’t do what you expect – if you’ve set an overclock previously.

Curiously enough, booting Fedora Linux from an USB stick did properly scale the CPU frequency based on the load, even with the overclock applied. Apparently only Windows or AMD’s drivers didn’t manage to do that. Booting a Linux helped me to rule out Ryzen Master as the root of the always applied overclock although the BIOS setting was set to the default Auto mode.

The takeaways:

  • Don’t overclock on this mainboard.
    • The OC options for the CPU are laughable at best. No way to set the multiplier per core.
  • Next time buy a higher-end mainboard for overclocking (ITX is expensive though…).

Kotlin Object Expression – What more can object do?

In a previous post I explained what Kotlin Object Declarations are. This time around it’s about the declaration’s sibling, the Object Expression.

An object is not just a glorified static replacement or a singleton. object can be used where Java usually utilizes anonymous inner classes. Let’s look at a more realistic scenario: a JButton and an ActionListener or a MouseListener.

Read More »

Kotlin Object Declarations – The fake-static

Instead of implementing my own backup application as I had planned a long time ago, I’m wandering off (re)learning Kotlin after a long absence from that language. In my defense though, I’m doing it in the context of the backup app which will not be Java as originally intended (or maybe later for comparison, who knows, I obviously can’t be trusted with my plans). Putting that aside, the most confusing concept of Kotlin for a Java developer is the object. What is that thing doing that a class can’t do and how do we declare static fields and methods? I know it’s nothing new, but that part seems to have changed a bit since I used Kotlin about two (?) years ago. So, for me this is a refresh of old information and also something new and by writing about it I will engrave it in my brain once and for all. And your confusion will hopefully turn into some productive… fusion… of some sort… or so.

Read More »

Red Dead Redemption 2

I’ve been a gamer for a very long time – it’s easily been twenty years or more (yes, I’m old). But, in the past year or so, my excitement has been waning. I have mentioned in another blog post that I was planning to replace my big tower PC with a notebook for (mobile) coding and writing – which I have done – and, in the short- to mid-term, get a gaming console to replace the video gaming part of the PC with something more casual and affordable. This day has finally come and the first game I have played has been Red Dead Redemption 2. Now, this game was many firsts for me:

  • First non-digital game since Steam has launched. I bought it in a retail store on a BluRay disc.
  • First full-price video game at 60€. Before that, I have always been shopping for special offers and discounts.
  • First console game.

I think Red Dead Redemption is something very special and I will try to explain why I think that is. One thing is for sure and that is the fact that it has rekindled the fire within me to play a video game on-end without pause. Unlike the other game reviews/experience reports I have written so far, this one is a bit different. I started writing when I was about 40% through the game and added to it at different stages of progress. In short: it’s like a diary.

Read More »

Unwanted JUnit 4 Dependency with Kotlin and JUnit 5

I ran across this issue only by accident because I was investigating a completely different problem. I wrote a quick test to debug my issue and was wondering why custom serializers and deserializers are not registered with the Jackson ObjectMapper. I had a nice init() function that was annotated with @Before. So, what the hell?

Let’s back up a bit for some context.

  • Kotlin Project
  • Runs on Java 12
  • JUnit 5 as test engine
  • AssertK for assertions (just for the sake of completeness)

I’m used to JUnit 4, so in my test I used @Before to annotate a setup method. It was one of the many options IntelliJ presented to me.

@Before
fun init() {
    val module = SimpleModule()
    module.addDeserializer(Instant::class.java, InstantDeserializer())
    module.addSerializer(Instant::class.java, InstantSerializer())
    mapper.registerModule(module)
}

The method wasn’t called, however. But it’s annotated! Well, it’s the wrong annotation if you’re using JUnit 5. The correct one is @BeforeEach. This one and @BeforeClass (new name @BeforeAll) have been changed from version 4 to 5 to make their meaning more obvious.

But that’s besides the point. The question is: where does this @Before come from then?

A look at the dependency tree quickly reveals the culprit.

It’s the official JetBrains Kotlin JUnit test artifact. Although it doesn’t hurt me to have it in my project, it certainly caused some confusion and I’d like to avoid that in the future. Hence, I excluded the old version of JUnit in my POM file for this dependency.

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-test-junit</artifactId>
    <version>${kotlin.version}</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Problem solved.

Of Affordable Phones, Software Updates and Yearly Upgrades

With the release of the Google Pixel 3a I once again started thinking about what I want in a smartphone. As a reminder, the last time I was pondering the purchase of one I was musing of tall phones, curved displays and notches. I am not in the market for a new phone right now as my iPhone 8 is more than capable of fulfilling my needs. But, with the recent launch of the Pixel 3a I wished that this device had already existed a year ago because it is basically the perfect phone for me. And I also wish Google would get back into the market of less expensive phones with the latest and greatest hardware as was the case with the Nexus line.

Read More »

AdoptOpenJDK 8 NullPointerException sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)

I recently had to deal with this little bugger as we moved from the OpenJDK 8 package supplied by the Linux distro of choice to AdoptOpenJDK 8. It is important to know that we completely uninstalled OpenJDK, including all its transient dependencies.

(And in due time we’ll uninstall Java 8 and replace that grandpa as well)

As a result, parts of our application didn’t work any longer, resulting in this nice and shiny Java stacktrace.

2019-05-03 08:22:07,345 ERROR [qtp1896708863-35] [PlotChartController] [/][/][/]- error while creating chart image
java.lang.NullPointerException
        at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
        at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)
        at sun.awt.FontConfiguration.init(FontConfiguration.java:107)
        at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774)
        at sun.font.SunFontManager$2.run(SunFontManager.java:431)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.font.SunFontManager.<init>(SunFontManager.java:376)
        at sun.awt.FcFontManager.<init>(FcFontManager.java:35)
        at sun.awt.X11FontManager.<init>(X11FontManager.java:57)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:442)
        at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
        at java.awt.Font.getFont2D(Font.java:491)
        at java.awt.Font.defaultLineMetrics(Font.java:2176)
        at java.awt.Font.getLineMetrics(Font.java:2246)
        at org.jfree.chart.axis.DateAxis.estimateMaximumTickLabelWidth(DateAxis.java:1453)
        at org.jfree.chart.axis.DateAxis.selectHorizontalAutoTickUnit(DateAxis.java:1365)
        at org.jfree.chart.axis.DateAxis.selectAutoTickUnit(DateAxis.java:1340)
        at org.jfree.chart.axis.DateAxis.refreshTicksHorizontal(DateAxis.java:1616)
        at org.jfree.chart.axis.DateAxis.refreshTicks(DateAxis.java:1556)
        at org.jfree.chart.axis.ValueAxis.reserveSpace(ValueAxis.java:807)
        at org.jfree.chart.plot.CombinedDomainXYPlot.calculateAxisSpace(CombinedDomainXYPlot.java:364)
        at org.jfree.chart.plot.CombinedDomainXYPlot.draw(CombinedDomainXYPlot.java:442)
        at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1235)
        at org.jfree.chart.JFreeChart.createBufferedImage(JFreeChart.java:1409)
        at org.jfree.chart.JFreeChart.createBufferedImage(JFreeChart.java:1389)
        at org.jfree.chart.ChartUtilities.writeChartAsPNG(ChartUtilities.java:183)

I obviously removed some (a lot) parts to make it more readable and to hide corporate IP 😉 But this is the relevant part.

I found this bug report on Github and for once, plowing through the comments, it helped me. As is mentioned there, the culprit is the missing “fontconfig” package. So, I added another Ansible task to our playbook to provision the server et voila, the problem is gone.

- name: Install fontconfig package
  package:
    name: fontconfig
    state: present
    tags:
      - java

As mentioned earlier, we had wiped all that was relevant to OpenJDK off the system and by doing so, also uninstalled the “fontconfig” package. Otherwise this error wouldn’t have surfaced. But that’s the benefit of starting with a clean slate. This way you know if something is missing and don’t get surprised by errors all of a sudden while, at the same time, it is working on another machine.

Micrometer and Spring (Non-Boot)

Almost all of the tutorials and blog posts I found on this topic were focused on Spring Boot because, starting with version 2, it uses Micrometer as its metrics framework. However, in a particular project at work we do not have access to Spring Boot let alone a recent Spring version. Therefore, I’m explaining how to include Micrometer in your non-Boot Spring application using XML configuration.

In this tutorial I will be using Spring 5 and Java 11, so not exactly the versions I’m dealing with at work, but the concepts are the same and everything can probably be copied exactly as shown here.

Read More »

A Java “DSL“ for Simple Unit Test Data Creation

I’m a person that usually writes tests before the implementation. In the context of my backup application project this has turned out to really slow me down. But it’s not just a problem of my personal projects. It also affects my professional work. 

Here’s the issue: for some tests you need test data and generating that test data can be a tedious task, depending on the complexity. This has caused me to procrastinate on my backup app. So, one evening, after having thought about this during a workout, I grabbed my laptop, sat down in my comfy bed and wrote a “DSL” that makes creating the data much simpler. Not only is it easier to create the data now, allowing me to continue at a faster pace, it’s also much more readable and the test setup doesn’t clutter the test case anymore. This is a very important aspect of a test. What good does it to have one if, after some time, you have to update it and don’t understand what it does anymore?

Read More »

The Writing Application Conundrum

While I’m actively procrastinating on my backup application and finishing my MacBook Pro review, I was pondering on what tool I should continue to use or start to use for writing my blog posts. I’ve tried a few things in the past, one of them being Markdown in Byword way back in the early stages of my blogging efforts, Libre Office and the ODT file format sometime after that and more recently Microsoft’s Word using its DOCX format. To generalize it a bit: 

  • Markdown using any capable editor.
  • A full featured Word processor.

Both tools have their pro’s and con’s, but none of them are the perfect solution and I’m finding myself doing a bit of this and a bit of that, but never being really satisfied.

Read More »